1.什么是跨域
跨域指的的浏览器不能执行其它网站的脚本。它是由浏览器的同源策略导致的,是浏览器对js实施的安全措施。
2.什么是同源策略
同源指的是:url的协议、域名、端口均为相同
如果没有同源策略限制,浏览器很容易受到XSS、CSFR等攻击。
同源策略限制以下几种行为:
1.Cookie、LocalStorage 和 IndexDB 无法读取
2.DOM和JS对象无法获得
3.AJAX 请求不能发送
3.常见的跨域场景
以url:http://www.domain.com为对比:
url | 说明 | 是否允许 |
---|---|---|
http://www.domain.com/a.js | 协议域名都相同,不同文件 | 允许 |
http://www.domain.com/b.js | 协议域名都相同,不同文件 | 允许 |
https://www.domain.com/a.js | 协议不相同 | 不允许 |
http://www.domain1.com/a.js | 主域名不相同 | 不允许 |
http://xxx.domain.com/a.js | 子域名不相同 | 不允许 |
http://www.domain.com:9000/a.js | 端口不相同 | 不允许 |
4.跨域解决方案
4.1 JSONP
实现原理:利用script标签src属性中的链接却可以访问跨域的js脚本,服务端不再返回JSON格式的数据,而是返回一段调用一个函数的js代码,然后将数据作为参数传递了过来,在src中进行了调用,这样实现了跨域。由于这种方式传参,jsonp只能发送get请求。
示例代码:
<script>
let script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数callback给后端,后端返回时执行这个在前端定义的回调函数并把数据传递过来
script.src = 'http://localhost:9500/login?callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数(接收数据)
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
4.2 跨域资源共享(CORS)
CORS 全称 Cross-origin Resource Sharing 中文名称 “跨域资源共享” 它突破了浏览器只能发送同源请求向服务器获取数据的限制。
它允许浏览器向跨域服务器跨域,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
需要在服务端设置:
Access-Control-Allow-Origin 表示允许跨域的来源
Access-Control-Allow-Methods 表示允许跨域方法
Access-Control-Allow-Headers 表示允许接受的自定义header字段名
Access-Control-Max-Age 表示预检请求的结果能够被缓存多久,即在多久内可以省略 预检请求
4.3 nginx代理跨域
nginx代理跨域,实质和CORS跨域原理一样,通过配置文件请求响应头实现
静态文件设置跨域:
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html index.htm;
# 使得html、js、css等文件可以跨域访问
add_header Access-Control-Allow-Origin *;
}
接口反向代理跨域
location ~* ^/(auth|function|admin){
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:9500';
add_header 'Access-Control-Allow-Methods' 'PUT,DELETE';
add_header 'Access-Control-Allow-Headers' 'Test-CORS, Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:9500';
add_header 'Access-Control-Allow-Credentials' 'true';
proxy_pass http://127.0.0.1:7000;
proxy_set_header Host $host;
}
4.4 document.domain + iframe跨域
此方案仅限主域相同,子域不同的跨域应用场景。
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
示例代码:
// 父子页面都设置document.domain为相同的域
<script>
document.domain = 'domain.com';
</script>
4.5 location.hash + iframe跨域
实现原理: a域与b域跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
4.6 postMessage跨域
postMessage是HTML5中为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
1、页面和其打开的新窗口的数据传递
2、多窗口之间消息传递
3、页面与嵌套的iframe消息传递
4、上面三个场景的跨域数据传递
4.7 WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。