同源策略与跨域

什么是同源策略?

官方参考: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:

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&param2=2"></script>
      并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
      callback({"name":"hax","gender":"Male"})
      这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
  • 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 等身份验证信息
      1. Access-Control-Allow-Origin: https://foo.example
      2. Access-Control-Allow-Methods: POST, GET, OPTIONS
      3. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
      4. Access-Control-Max-Age: 86400