简介
本文主要是阐述与总结现代浏览器的跨域问题
同源策略
同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
定义
如果两个 URL 的 protocol、port (en-US) (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)。
下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:
URL | 结果 | 原因 |
---|---|---|
http://store.company.com/dir2/other.html | 同源 | 只有路径不同 |
http://store.company.com/dir/inner/another.html | 同源 | 只有路径不同 |
https://store.company.com/secure.html | 失败 | 协议不同 |
http://store.company.com:81/dir/etc.html | 失败 | 端口不同 (http:// 默认端口是80) |
http://news.company.com/dir/other.html | 失败 | 主机不同 |
开始一个跨域请求
你可以使用XMLHttpRequest
或Fetch
发起一个跨域请求
你可以在网站http://foo.com
发起一个对http://bar.com
的请求,如果对方网站许可,那么便能拿到对应的响应,否则则失败。
请求分两类
预检请求
预检请求是一个OPTIONS 请求,在跨域时预先发送到服务端以获取该服务器对跨域访问控制的一些配置,以决定接下来的请求是否会被发送。一般以Header
头的形式返回, 相关配置一般以Access-Control-*
作为开头
实际请求
简单请求
简单请求不会触发CORS 预检请求
若请求满足所有下述条件,则该请求可视为”简单请求”:
- 使用下列方法之一:
- GET
- HEAD
- POST
- 除了被用户代理自动设置的首部字段(例如
Connection
,User-Agent
)和在Fetch
规范中定义为禁用首部名称
的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (需要注意额外的限制)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
Content-Type
的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
- 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
- 请求中没有使用 ReadableStream 对象。
复杂请求
除了简单请求以外的所有请求都被称为复杂请求,复杂请求在进行跨域访问前会发送一个 CORS 预检请求
跨域请求响应Headers
跨域时携带Cookies
需要确保请求发起时信任对方
1 | fetch('http://bar.com', { |
credentials
含义:
- “omit”: Excludes credentials from this request, and causes any credentials sent back in the response to be ignored.
- “same-origin”: Include credentials with requests made to same-origin URLs, and use any credentials sent back in responses from same-origin URLs.
- “include”: Always includes credentials with this request, and always use any credentials sent back in the response.
或
1 | const req = new XMLHttpRequest(); |
需要确保服务端响应头返回
1 | Access-Control-Allow-Credentials: true |
注意此时Access-Control-Allow-Origin
不能为 “\“*
需要确保要发送的Cookie满足SameSite条件
注意Chrome 80 后将默认值从原来的None
改为Lax
, 相关影响可以看如下文章