1、什么是同源策略?
同源策略是浏览器中一项基本的安全策略,是指从一个源中加载的文档或脚本与来自不同源的资源之间的交互会被浏览器所限制。同源策略中的同源指的是,协议、域名、端口均相同。
比如:https://www.youkuaiyun.com/index.html 这个网站,协议是https,域名是www.youkuaiyun.com,端口是80(默认端口)。它的同源情况如下:
https://www.youkuaiyun.com/other.html:同源
http://www.youkuaiyun.com/other.html:不同源,协议不同
https://www.csdn.com/other.html:不同源,域名不同
https://www.youkuaiyun.com:81/other.html:不同源,端口不同
同源策略主要是为了保护用户信息的安全,受到同源策略限制的主要有以下几种行为:
1.、Cookie、LocalStorage和IndexedDB无法读取。
2、DOM无法操作。
3、AJAX请求发送后,结果被浏览器拦截。
2、为什么会产生跨域?
跨域是由于浏览器的同源策略导致的,是浏览器对JavaScript实施的安全限制。当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
3、如何解决跨域?
下面简单说明一下日常开发中比较常用的方法。
1、JSONP
JSONP是服务器与客户端跨源通信的常用方法。最大特点是简单适用,兼容性好(兼容低版本IE)。缺点是只支持GET请求,不支持POST请求。
核心思想:网页通过添加一个<script>
元素,向服务器请求JSON数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
(1)原生实现:
//向服务器demo.com发出请求,改请求的查询字符串中有一个callback参数,用来指定回调函数的名字
<script src="ttps://demo.com/sug?code=utf-8&q=手机&&callback=doSomething"></script>
//处理服务器返回回调函数的数据
<script type="text/javascript">
function doSomething(data){
//处理获得的数据
console.log(res.data);
}
</script>
(2)jQuery ajax:
jQuery中的$.ajax
方法也直接支持使用jsonp协议进行跨域访问。代码就是在ajax参数中再增加一个dataType:’jsonp’
参数。代码如下:
$.ajax({
type:'get',
dataType:'jsonp',//jsonp跨域
url:'https://demo.com/sug?code=utf-8&q=手机',
success:function(data){
console.log(data);
},
error:function(XMLHttpRequest, textStatus, errorThrown){
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(textStatus);
}
});
(3)使用jQuery提供的一个插件jquery-jsonp。代码如下:
$.jsonp({
type:'get',
url:'ttps://demo.com/sug?code=utf-8&q=手机',
callbackParameter:"callback",
dataFilter:function(json){
console.log(json);
return json;
},
success:function(data){
console.log(data);
},
error:function(msg){
console.log(msg);
}
});
注意在这里多了callbackParameter:”callback”
这行代码,不加是会报错的。jsonp的dataFilter中的数据直接转换成json对象了。
(4)Vue.js
this.$http.jsonp(‘http://www.domain2.com:8080/login’, {
params: {},
jsonp: ‘handleCallback’
}).then((res) => {
console.log(res);
})
2、CORS(Cross-Origin Resource Sharing):跨域资源共享。它是W3C标准,属于跨源ajax请求的根本解决方法。
1、普通跨域请求:只需要服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
【前端设置】根据xhr.withCredentials字段判断是否带有cookie
①原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
② jQuery ajax
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
③vue-resource
Vue.http.options.credentials = true
④ axios
axios.defaults.withCredentials = true
至于服务端设置根据自行查询。