1、浏览器的同源策略
同源策略/**SOP(Same origin policy)**是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。
所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
http://www.example.com/detail.html
https://www.example.com/detail.html 协议不同
http://api.example.com/detail.html 域名不同
http://www.example.com:8080/detail.html 端口不同
2、跨域解决方案
- jsonp
- document.domain + iframe 跨域
此方案仅限主域相同,子域不同的跨域应用场景。 - nginx 代理跨域
- nodejs 中间件代理跨域
- 后端在头部信息里面设置安全域名
3、jsonp实现跨域的原理
function foo(data){
console.log(data);
}
var script = document.createElement("script");
script.src = 'http://localhost:8080/hello.php?callback=foo&username=zhangsan&password=123';
var head = document.getElementsByTagName("head")[0];
head.appendChild(script);
- jsonp从本质上讲,是通过动态创建script标签,然后通过src属性发送跨域请求,服务器端响应数据格式为【函数调用】。
4、利用jQuery实现跨域
主要属性设置:
- dataType
必须为jsonp - jsonp
jsonp属性用于设置自定义参数名,即callback=abc中的callback,后端会根据jsonp属性的值获取方法名,jquery默认是callback - jsonpCallback
用于自定义回调函数名,即callback=abc中的abc
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery中jsonp的使用</title>
<script src="./jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function (){
$("#btn").click(function (){
$.ajax({
type: 'get',
url: 'http://localhost:8080/jsonp.php',
dataType: 'jsonp',
jsonp: 'cb', //jsonp属性用于自定义参数名,即callback=abc中的callback,后端会根据jsonp属性的值获取方法名,jquery默认是callback
jsonpCallback: 'abc', //jsonpCallback属性用于自定义回调函数名,即callback=abc中的abc
success: function (data){
console.log(data);
},
error: function (){
console.log("error");
}
});
});
})
</script>
</head>
<body>
<input type="button" value="点击" id="btn" />
</body>
</html>
后端:
<?php
$cb = $_GET['cb'];
$arr = array("username"=>"张三", "password"=>"123");
echo $cb.'('.json_encode($arr).')';
?>
5、模仿jQuery实现跨域
function ajax(obj){
var defaults = {
type: 'get',
async: true,
url: '#',
dataType: 'text',
jsonp: 'callback',
data: {},
success: function (data){
console.log(data);
}
};
for (var objKey in obj) {
defaults[objKey] = obj[objKey];
}
if (defaults.dataType == 'jsonp'){
ajax4Jsonp(defaults);
} else {
ajax4Json(defaults);
}
}
function ajax4Jsonp(defaults){
// 回调函数名称
// jQuery中的默认函数名为:expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
var version = "1.12.4";
var callbackName = "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ) + "_" + (new Date().getTime());
// 如果传递了回调函数名称
if (defaults.jsonpCallback){
callbackName = defaults.jsonpCallback;
}
// 定义回调函数,由服务器响应内容来调用,向window中添加方法
window[callbackName] = function (data){
// 调用success方法
defaults.success(data);
};
// 入参的处理
var param = '';
for (var attr in defaults.data){
param += '&' + attr + "=" + defaults.data[attr];
}
// 动态创建script标签
var script = document.createElement("script");
script.src = defaults.url + "?" + defaults.jsonp + "=" + callbackName + param;
var head = document.getElementsByTagName("head")[0];
head.appendChild(script);
}
function ajax4Json(defaults){
// 创建XMLHttpRequest对象
var xhr = null;
if (window.XMLHttpRequest){
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// 处理get请求参数
var param = null;
if (defaults.type == "get"){
for (var deKey in defaults.data) {
param += "&" + deKey + "=" + defaults.data[deKey];
}
defaults.url += "?" + param;
}
// 准备发送
xhr.open(defaults.type, defaults.url, defaults.async);
// 处理post请求参数
if (defaults.type == "post"){
param = defaults.data;
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
// 执行发送
if (param){
xhr.send(param);
} else {
xhr.send(null);
}
// 处理异步和同步
if (!defaults.async) {
// 如果是同步
if (defaults.dataType == "json"){
return JSON.parse(xhr.responseText);
} else {
return xhr.responseText;
}
}
// 如果是异步
xhr.onreadystatechange = function (){
if (xhr.readyState == 400){
if (xhr.status == 200){
var response = xhr.responseText;
if (defaults.dataType == "json"){
defaults.success(JSON.parse(response));
} else {
defaults.success(response);
}
}
}
};
}
测试:
// ajax({
// type:'get',
// // url:'http://localhost:8080/jsonp.php',
// dataType:'json',
// success:function(data){
// console.log(data.username,data.password);
// }
// });
ajax({
type:'get',
url:'http://localhost:8080/jsonp.php',
dataType:'jsonp',
data:{username:'zhangsan',password:'123'},
jsonp:'cb',
jsonpCallback:'abc',
success:function(data){
console.log(data.username,data.password);
}
});
245

被折叠的 条评论
为什么被折叠?



