什么是跨域?
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略导致的,是浏览器对 JavaScript 实施的安全限制。
同源策略是一个重要的安全策略,它用于限制一个 origin 的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。-- MDN
只有当域名、协议、端口三者一致时,才是同源。
同源才不会受到浏览器的同源策略限制,否则就需要跨域。
最经典的跨域方案 JSONP
jsonp 的原理是利用<script>
标签不受同源策略限制的特性来进行跨域操作。但它只能用来发送 GET 请求。
在客户端和服务端定义一个函数,当客户端发起一个请求时,服务端返回一段 javascript 代码,其中调用了在客户端定义的函数,并将相应的数据作为参数传入该函数。
function jsonp_cb(data) {
console.log(data);
}
function ajax() {
var url = 'http://xx.com/test.php?jsonp_callback=jsonp_cb';
var script = document.createElement('script');
// 发送请求
script.src = url;
document.head.appendChild(script);
}
ajax();
服务端获取到 jsonp_callback 传递的函数名 jsonp_cb,返回一段对该函数调用的 js 代码
jsonp_cb({
name: 'story',
});
最流行的跨域方案 CORS
CORS(跨域资源共享)是一种跨域访问的机制,可以让 AJAX 实现跨域访问。它允许一个域上的脚本向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应头即可。
Access-Control-Allow-Origin: * // 允许来自任何域的请求,不安全
Access-Control-Allow-Origin: https://arvinxiang.com/ // 仅允许来自特定域的请求
当客户端的 ajax 请求的 url 为其他域时,对于支持 CORS 的浏览器,请求头会自动添加 Origin,值为当前 host。
var xhr = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';
xhr.open('GET', url, true);
xhr.send();
CORS 默认不发送 cookie,如果要发送 cookie,需要设置 withCredentials
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
同时,服务端也要设置
Access-Control-Allow-Credentials: true
最方便的跨域方案 Nginx
nginx 作为代理服务器将请求转发给后端服务,这样就规避了同源策略。
在网站的配置文件里增加以下配置:
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
img ping
img 标签也是没有跨域限制的,但它只能用来发送 GET 请求,且无法获取服务端的响应文本,可以利用它实现一些简单的、单向的跨域通信,常用于数据上报;
var img = new Image();
img.onload = function () {
console.log('done');
img.onload = null;
img = null;
};
img.src = 'http://xx/xx.gif';
其他跨域方案
- window.name + iframe
- location.hash + iframe
- document.domain + iframe
- window.postMessage
- websocket
参考
https://www.ruanyifeng.com/blog/2016/04/cors.html https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS https://livebook.manning.com/book/cors-in-action/chapter-6/262