跨域问题
2016-12-21
同源策略
什么是同源,满足三个条件相同
- 协议, http与https不同源
- 端口,80与8080 不同源
- 主机 www.company.com与store.company.com不同源
Ps. IE例外:不考虑端口;Trust Zones(可信任的域)的域名可以看作是同源
同源策略的限制
- 通常允许进行跨域写操作(Cross-origin writes)。例如链接(links),重定向以及表单提交。
- 通常允许跨域资源嵌入(Cross-origin embedding)。就是跨域标签了
<scipt>
,<link>
,<img>
,<video>
,<object>
,<iframe>
- 通常不允许跨域读操作(Cross-origin reads)。但常可以通过内嵌资源来巧妙的进行读取访问。
如何阻止跨源访问
- 阻止跨域写操作,只要检测请求中的一个不可测的标记(CSRF token)即可,这个标记被称为Cross-Site Request Forgery (CSRF) 标记。必须使用这个标记来阻止页面的跨站读操作。
- 阻止资源的跨站读取,需要保证该资源是不可嵌入的。阻止嵌入行为是必须的,因为嵌入资源通常向其暴露信息。
- 阻止跨站嵌入,确保你得资源不能是以上列出的可嵌入资源格式。多数情况下浏览器都不会遵守Conten-Type消息头。例如,如果你在
<script>
标签中嵌入HTML文档,浏览器仍将HTML解析为Javascript。当你的资源入口不是指向你的网站, 你同样可以使用CSRF token阻止它嵌入.
document.domain
如果是父子域跨域的情况,可以通过修改document.domain实现父子域同源
如站点store.company.com, 需要访问company.com/api
1 | document.domain = 'company.com' |
(待验证)
HTTP控制访问CORS
简单请求
如:get一个数据
post也可以,但是Content-Type只能是这三种之一
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
预请求
先发一个options请求,再发正式请求
如:上传文件,想要使用自定义的请求头,如:x-modified
响应头说明
Access-Control-Allow-Origin
允许来自哪些域的请求
出于安全性的考虑,如果客户端xhr指定了withCredentials=true
,那么这个值是不能为*
,必须指定有哪些域可访问的,确保了登陆态只能给我事前设置好的站点,
Access-Control-Expose-Headers
指定浏览器可以得到服务器的那些自定义的响应头信息,在预请求中,而不是正式请求,这和Access-Control-Allow-Headers是不一样的,这些头预请求的响应头,而不是正式请求的请求头
Access-Control-Max-Age
预请求的结果的有效期是多少,单位(秒)
浏览器关掉后就无效了,应该是这样,待验证
Access-Control-Allow-Credentials
首先这个响应头的值是true或false,如果是true,服务端才把响应数据返回给客户的,否则不返回
服务端是会根据客户端传过来的cookie判断身份信息是否有效,然后决定返回true还是false??
客户端xhr中的withCredentials
属性可以决定客户端是不是要把cookie信息带上给服务端
在用一个站点下使用withCredentials
属性是无效的。
Access-Control-Allow-Methods
告诉客户端,服务端同意这些请求的方式,比如:get post options
Access-Control-Allow-Headers
预请求中指定服务器在正式的请求中会识别哪些请求头,就是预请求服务同意了哪些header,告诉客户端可以发起Access-Control-Request-Headers
请求头说明
Origin
告诉服务器端,这个请求的来源是哪里,这个值当然就是请求当前所处的域,不包含任何路径信息
Access-Control-Request-Method
告诉服务端,实际请求的方式是什么
Access-Control-Request-Headers
告诉服务端,自定义的header是哪些
兼容性
移动端可以认为全兼容
PC端,Internet Explorer 8 和 9 通过 XDomainRequest 对象来实现CORS,其他也都ok