跨域
如果协议、域名或者端口有一个不同就是跨域。
同源策略
推荐阅读:浏览器同源政策及其规避方法
因为浏览器出于安全考虑(主要用来防止 CSRF 攻击),制定了同源策略,意思就是跨域时 Ajax 请求会失败。
问题:
然而同源策略还是不能完全阻止 CSRF,它只是把 Response 给拦截了,就是请求还是发出去了。
换句话说只能阻止获取 Response 的信息,不能阻止发送请求。
例子:
有个恶意网站,一打开就会跨域发送这样一个请求,ajax 直接发出去 https://xxx.com/trade?money=1000&userId=666 (xhr.withCredentials = true 时还会带上cookie)
虽然 xhr 的 response 恶意网站收不到,但是这个请求确确实实发出去了
结论:
因此,真正的安全应该在服务端做好。例如,cookie 和 ip 绑定、检查 reference、用 token 来替代 cookie,这些都是解决csrf 的方法。
跨域请求
因为这个不太靠谱的同源策略的存在,我们不得不通过一些手段,去实现跨域请求。
JSONP
利用 script、img 的 src 不受同源策略限制的特点,发送跨域的 GET 请求。
实现这个需要前后端都改写。
例如:
<script src="http://domain/api?param1=a¶m2=b&callback=xxx"></script> <script> function xxx(data) { console.log(data) } </script>
GET http://domain/api?param1=a¶m2=b&callback=xxx 会返回这样的
xxx({
errCode: 0,
data: {
list: [{age: 1}, {age: 2}, {age: 3}, {age: 4}, {age: 5}],
page: 1,
size: 5,
total: 100
}
})
上面定义的全局函数xxx,就可以接受到服务器返回的 data 了
CORS
Cross-origin resource sharing 跨域资源分享
这个十分简单,只需要后端改写一下,加几个 Access-Control-Allow-xxx 的响应头就可以了。前端完全不用修改,跨域请求当作正常请求来发送就可以了。
很早之前就写过博文了,这里就不细说了:Ajax跨域CORS
document.domain + iframe
document.domain 如果能设置成一致的话,2个页面就可以通过 iframe 通信,互相操作。
当然 document.domain 只能设置成自己或者比自己更高级的域名,例如 xxx.qq.com 只能设置成 xxx.qq.com 或者 qq.com
例如这样可以拿到 iframe 的 window 对象,这样就可以操作这个页面了。
// 拿到 iframe 的 window document.querySelector('iframe').contentWindow // iframe 也能拿到 宿主的window window.parent
但是如果 document.domain 不一致,就会报跨域的错。
postMessage
// 发送方 let otherWin = window.open('https://www.qq.com'); otherWin.postMessage('信息xxx', '*'); // 接收方 window.addEventListener('message', ev => { console.log(ev.data); })