1. 什么是跨域
跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。
什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指”协议+域名+端口”三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
常见跨域场景
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.domain.com/a.js 与 http://www.domain.com/b.js 与 http://www.domain.com/lab/c.js | 同一域名,不同文件或路径 | 允许 |
http://www.domain.com:8000/a.js 与 http://www.domain.com/b.js | 同一域名,不同端口 | 不允许 |
http://www.domain.com/a.js 与 https://www.domain.com/b.js | 同一域名,不同协议 | 不允许 |
http://www.domain.com/a.js 与 http://192.168.4.12/b.js | 域名和域名对应相同ip | 不允许 |
http://www.domain.com/a.js 与 http://x.domain.com/b.js 与 http://domain.com/c.js | 主域相同,子域不同 | 不允许 |
http://www.domain1.com/a.js 与 http://www.domain2.com/b.js | 不同域名 | 不允许 |
跨域解决方案
- 通过jsonp跨域
//原生实现
<script>
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));
}
</script>
//JQuery实现
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
//vue实现
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'onBack'
}).then((res) => {
console.log(res);
})
- document.domain + iframe跨域
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
<script>
document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
</script>
-
location.hash + iframe跨域
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。 -
window.name + iframe跨域
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。 -
postMessage跨域
-
跨域资源共享(CORS)
-
nginx代理跨域
-
Nodejs中间件代理跨域
-
WebSocket协议跨域