同源策略与跨域
什么是同源策略?
官方参考:MDN 同源策略
定义:如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin)。
本域脚本只能读写本域内的资源,而无法访问其它域的资源。
哪些请求会命中同源策略
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#what_requests_use_cors
This cross-origin sharing standard can enable cross-site HTTP requests for:
- Invocations of the XMLHttpRequest or Fetch APIs, as discussed above.
- Web Fonts (for cross-domain font usage in @font-face within CSS), so that servers can deploy TrueType fonts that can only be loaded cross-site and used by web sites that are permitted to do so.
- WebGL textures.
- Images/video frames drawn to a canvas using drawImage().
- CSS Shapes from images.
This is a general article about Cross-Origin Resource Sharing and includes a discussion of the necessary HTTP headers.
如何进行跨域?
- JSONP 策略:和服务端约定好一个函数名,当请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了约定好的函数,并且将数据当做参数传入。
- 注:JSONP 只能够支持
GET
请求的跨域 - 利用
<script>
标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>
元素,地址指向第三方的API网址,形如:<script src="http://www.example.net/api?param1=1¶m2=2"></script>
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:callback({"name":"hax","gender":"Male"})
这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
- 注:JSONP 只能够支持
- document.domain 策略:1)有其他页面 window 对象的引用。2)一级域名相同。3)协议相同。4)端口相同。使用方法就是将符合上述条件页面的 document.domain 设置为同样的一级域名。
- window.name 由于 window.name 不随着 URL 的跳转而改变,所以可以用于传递信息,一般用于 iframe 的情形
- window.postMessage() 实现了 window 对象之间的跨域信息传递,使用
window.addEventListener('message', callback)
即可以实现通信。- Javascript的APIs中,如 iframe.contentWindow, window.parent, window.open 和 window.opener 允许文档间直接相互引用。当两个文档的源不同时,这些引用方式将对 Window 和 Location对象的访问添加限制。可以使用window.postMessage 作为替代方案,提供跨域文档间的通讯。
- Flash 跨域 / iFrame 跨域
- CORS 跨域:支持
POST
的跨域方式,具体方法在于修改或添加 HTTP 头中的:access-control-allow-origin: *
将会允许任何域的跨域请求。- withCredentials = true 会带上 Cookie 等身份验证信息
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
- withCredentials = true 会带上 Cookie 等身份验证信息