跨域?
当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。——MDN
- 比如,站点 domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 domain-b.com/image.jpg。
- 比如,站点 domain-a.com 的某 HTML 页面通过 <script> 的 src 请求 domain-b.com/util.js。
- ...
浏览器的同源策略
如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。 ——MDN
同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
浏览器会报跨域错误
出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非
响应报文包含了正确CORS响应头。
CORS (Cross-Origin ResourceSharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。——MDN
浏览器的同源安全策略默认阻止“跨域”获取资源。但是 CORS给了web服务器这样的权限,即服务器可以选择,允许跨域请求访问到它们的资源。——MDN
跨域资源共享下的预检查
简单请求和非简单请求请参考文章[1],简单请求不会触发预见
跨域资源共享标准新增了一组 HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。——MDN
预检请求
与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
预检请求完成之后,发送实际请求
预检请求头中同时携带的首部字段:Access-Control-Request-Method告知服务器,实际请求将使用什么请求方法; Access-Control-Request-Headers告知服务器,实际请求将携带几个自定义请求首部字段。
预检响应头中同事响应的首部字段:Access-Control-Allow-Methods 表明服务器允许客户端使用方法发起请求。该字段与 HTTP/1.1 Allow: response header 类似,但仅限于在需要访问控制的场景中使用。 首部字段 Access-Control-Allow-Headers 表明服务器允许请求中携带字段。与 Access-Control-Allow-Methods 一样,Access-Control-Allow-Headers 的值为逗号分割的列表。首部字段 Access-Control-Max-Age 表明该响应的有效时间,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。