同源策略
浏览器的同源策略了,它规定了协议号-域名-端口号这三者必须都相同才符合同源策略
如有有一个不相同,就会出现跨域问题,不符合同源策略导致的后果有
- LocalStorge、SessionStorge、Cookie等浏览器内存无法跨域访问
- DOM节点无法跨域操作
- Ajax请求无法跨域请求
以下三个标签不受同源策略影响
- script标签:
<script src="加载资源路径"></script> - link标签:
<link herf="加载资源路径"></link> - img标签:
<img src="加载资源路径"></img>
跨域的时机
请求发出去到后端,后端返回数据,在浏览器接收后端数据时被浏览器的跨域报错拦下来
跨域解决方案
1、JSONP
简单例子
如客户想访问 : www.xx.com/jsonp?jsonc…
假设客户期望返回数据:["customername1","customername2"]
真正返回到客户端的数据显示为: callbackFunction(["customername1","customername2"])。
服务端代码
response.getOutputStream().write("callbackFunction([\"customername1\",\"customername2\"])".getBytes());
客户端代码
<script type="text/javascript">
function callbackFunction(result, methodName)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
</script>
2、WebSocket
WebSocket不附属于同源策略,它本身就有意被设计成可以跨域的一个手段。由于历史原因,跨域检测一直是由浏览器端来做,而WebSocket的跨域检测由服务端做,浏览器仍然会带上一个Origin跨域请求头,服务端则根据这个请求头判断此次跨域WebSocket请求是否合法
3、Cors
Cors,全称是Cross-Origin Resource Sharing,意思是跨域资源共享,Cors一般是由后端来开启的,一旦开启,前端就可以跨域访问后端
Cors涉及的响应头
Access-Control-Allow-Origin
标识允许哪个域的请求
常用值: *,或指定域名(如果为* 则浏览器不会发送cookie)
Access-Control-Allow-Credentials
是否携带认证信息(cookie),如果为false,即使响应头有Set-Cookie,浏览器也不会理会,也不会发送Cookie
常用值:true|false
Option请求
浏览器在发送跨域请求并且包含自定义 header 字段时,浏览器会先向服务器发送 OPTIONS 预检请求,探测该请求服务是否允许自定义跨域字段,服务器需要适当的作出应答。
如果请求是 simple headers 方式则不会发送预检请求(Accept、Accept-Language、Content-Language、Content-Type),当仅包含这些请求头且满足以下要求时,则不需要发送预检请求。
- 对于
Accept-Language和Content-Language:只能存在值0-9,A-Z,a-z,空间或*,=.;=。- 关于
Accept和Content-Type:不能包含 CORS 不安全的请求头字节:"():<>?@[]{},Delete,Tab和控制字符:0x00到0x19。Content-Type:需要有一个 MIME 类型的值(忽略参数)。可以是application/x-www-form-urlencoded、multipart/form-data或text/plain的任意一个。- 对于任何
header:值的长度不能大于 128。
预检请求会多两个头信息
Access-Control-Request-Method
该次请求的请求方式
Access-Control-Request-Headers
该次请求的自定义请求头字段
预检请求通过后服务器做出响应
//指定允许其他域名访问
'Access-Control-Allow-Origin:http://172.20.0.206'
//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
'Access-Control-Allow-Credentials:true'
//预检结果缓存时间
'Access-Control-Max-Age: 1800'
//允许的请求类型 满足服务器要求的所有请求方式,请求头,不限于该次请求
'Access-Control-Allow-Methods:GET,POST,PUT,POST,DELETE,HEAD'
//允许的请求头字段 满足服务器要求的所有请求方式,请求头,不限于该次请求
'Access-Control-Allow-Headers:x-requested-with,content-type'
后端代码
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "*");
4、代理
同源策略它只是浏览器的一个策略,它是限制不到后端,,所以可以通过代理(node,或nginx),先访问代理,再让代理访问后端拿到数据
5、document.domain && iframe
场景:a.xx.com/index.html 与 b.xx.com/index.html之间的通信
他们的一级域名都是xx.com,这使得他们可以通过document.domain && iframe的方式来通信