跨域

155 阅读3分钟

同源策略

浏览器的同源策略了,它规定了协议号-域名-端口号这三者必须都相同才符合同源策略

如有有一个不相同,就会出现跨域问题,不符合同源策略导致的后果有

  • 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-9A-Za-z,空间或 *,=.;=
  • 关于 Accept 和 Content-Type:不能包含 CORS 不安全的请求头字节:"():<>?@[]{}DeleteTab 和控制字符:0x00 到 0x19
  • Content-Type:需要有一个 MIME 类型的值(忽略参数)。可以是 application/x-www-form-urlencodedmultipart/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的方式来通信