本帖最后由 李盼盼老师 于 2018-4-19 16:49 编辑
【什么是跨域】 只要协议、域名、端口有任何一个不同,都被当作是不同的域,他们之间的请求就是跨域操作。 浏览器的同源策略会导致跨域,这里同源策略又分为以下两种 1. DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。 2. XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。 同源策略限制以下几种行为: 1.) Cookie、LocalStorage和 IndexDB 无法读取 2.) DOM 和 Js对象无法获得 3.) AJAX 请求不能发送
【常见的跨域解决方案】 - 通过jsonp跨域
- document.domain + iframe跨域
- postMessage跨域跨域资源共享(CORS)
【通过jsonp跨域】 通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。 1.)原生实现: [JavaScript] 纯文本查看 复制代码 var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack'; document.head.appendChild(script);
// 回调执行函数
function onBack(res) { alert(JSON.stringify(res)); }
服务端返回如下(返回时即执行全局函数)
onBack({"status": true, "user": "admin"}) 2.)jqueryajax: [JavaScript] 纯文本查看 复制代码 $.ajax({[/align]
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
jsonp缺点:只能实现get一种请求
3.)vue.js [JavaScript] 纯文本查看 复制代码 this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'onBack'
}).then((res) => {
console.log(res);
})
【document.domain+ iframe跨域】 此方案仅限主域相同,子域不同的跨域应用场景 实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。 [JavaScript] 纯文本查看 复制代码 <iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
[JavaScript] 纯文本查看 复制代码 document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
【跨域资源共享(CORS)】 普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。 需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,可参考下文:七、nginx反向代理中设置proxy_cookie_domain 和八、NodeJs中间件代理中cookieDomainRewrite参数的设置。
目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。 1、 前端设置: 1.)原生ajax [JavaScript] 纯文本查看 复制代码 // 前端设置是否带cookie
xhr.withCredentials = true;
示例代码:
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);
}
};
2.)jQuery ajax [JavaScript] 纯文本查看 复制代码 $.ajax({
...
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
...
}); 3.)vue框架 在vue-resource封装的ajax组件中加入以下代码: [JavaScript] 纯文本查看 复制代码 Vue.http.options.credentials = true 2、 服务端设置: 若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。
|