导航
CORS 允许服务器在响应头中指定允许的来源域。前端通过标准的 XMLHttpRequest 或 Fetch 请求与不同域的服务器通信。
而在 CORS 中会有 简单请求
和 复杂请求
的概念。
简单请求不会触发 CORS 预检请求。这样的请求为“简单请求”。
简单请求是一种跨域请求,但由于它满足一组特定的条件,浏览器会直接发送实际的请求,而不需要发送预检请求。这是跨域请求中的一种优化,可以减少不必要的网络请求。
简单请求同时满足以下条件:
application/x-www-form-urlencoded
、multipart/form-data
和 text/plain
)XMLHttpRequestUpload
对象均没有注册任何事件监听器。ReadableStream
对象。FormData
对象。除以上情况外的。
复杂请求不符合简单请求的条件,通常是因为请求方法是非标准的或者包含自定义头信息。对于复杂请求,浏览器会发送预检请求(OPTIONS 请求)到目标服务器,以获取服务器是否允许跨域请求的信息。
Authorization
、X-Requested-With
。multipart/form-data
。XMLHttpRequestUpload
或 ReadableStream
。FormData
对象上传数据,其中包含文件。app.use(async (ctx, next) => {
ctx.set("Access-Control-Allow-Origin", ctx.headers.origin);
ctx.set("Access-Control-Allow-Credentials", true);
ctx.set("Access-Control-Request-Method", "PUT,POST,GET,DELETE,OPTIONS");
ctx.set(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, cc"
);
if (ctx.method === "OPTIONS") {
ctx.status = 204;
return;
}
await next();
});
想要传递 cookie
需要满足 3 个条件
withCredentials
这里默认情况下在跨域请求,浏览器是不带 cookie 的。但是我们可以通过设置 withCredentials
来进行传递 cookie
.
// 原生 xml 的设置方式
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// axios 设置方式
axios.defaults.withCredentials = true;
Access-Control-Allow-Credentials
为 true
Access-Control-Allow-Origin
为非 *
这里请求的方式,在 chrome
中是能看到返回值的,但是只要不满足以上其一,浏览器会报错,获取不到返回值。
Access to XMLHttpRequest at '<http://127.0.0.1:8080/api/corslist>' from origin '<http://127.0.0.1:8000>' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Access to XMLHttpRequest at '<http://127.0.0.1:8080/api/corslist>' from origin '<http://127.0.0.1:8000>' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
分别演示一下前端部分 简单请求
和 非简单请求
****
<script src="<https://cdn.bootcss.com/axios/0.19.2/axios.min.js>"></script>
<script>
axios.get("<http://127.0.0.1:8080/api/corslist>");
</script>
这里我们加入了一个非集合内的 header
头 cc
来达到非简单请求的目的。
<script src="<https://cdn.bootcss.com/axios/0.19.2/axios.min.js>"></script>
<script>
axios.get("<http://127.0.0.1:8080/api/corslist>", { header: { cc: "xxx" } });
</script>
在新版的 chrome 中,如果你发送了复杂请求,你却看不到 options
请求。可以在这里设置 chrome://flags/#out-of-blink-cors
设置成 disbale
,重启浏览器。对于非简单请求就能看到 options
请求了。