浏览器为了安全性,默认禁止读取不同源的资源(包括 Cookie、DOM、LocalStorage 和 AJAX 请求)。 同源必须同时满足:协议 (protocol)、域名 (domain) 和 端口 (port) 完全一致。
违规示例:
http://a.com 到 https://a.com (协议不同)http://a.com 到 http://b.com (域名不同)http://a.com:80 到 http://a.com:8080 (端口不同)CORS 是浏览器的安全机制,允许服务器声明“哪些源可以访问我的资源”。
CORS 请求分为两类:简单请求 和 预检请求 (Preflight)。
浏览器直接发送请求,带上 Origin: <当前源>。服务器响应头必须包含:
Access-Control-Allow-Origin: * 或 <Origin>Access-Control-Allow-Credentials: true (如果带 Cookie)浏览器必须先发送一个 OPTIONS 请求进行询问(预检)。
OPTIONS 请求头:
Access-Control-Request-Method: PUTAccess-Control-Request-Headers: content-type服务器响应头:
Access-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: content-typeAccess-Control-Max-Age: 86400 (缓存预检结果,减少请求)默认情况下,跨域请求不携带 Cookie。如果需要携带(例如保持登录状态):
withCredentials: true。Access-Control-Allow-Origin 不能是 *,必须写死具体的域名(如 http://localhost:3000)。Access-Control-Allow-Credentials: true。JSONP 利用 <script> 标签不受同源策略限制。
<script src="http://api.com?callback=fn">,服务端返回JS代码 fn({ data: ... })。proxy_pass 转发请求,浏览器以为请求的是同源服务器(实际上 Nginx 去请求了后端),彻底绕开浏览器同源策略。Allow-Origin: *。