如果 POST 不在预检选项响应的 Access-Control-Allow-Methods 值中,浏览器会阻止 POST 请求吗?
Do browsers block POST requests if POST isn’t in the Access-Control-Allow-Methods value of the preflight OPTIONS response?
我认为我对 CORS 非常了解,但我仍然对浏览器在预检请求方面的行为感到困惑。
假设浏览器发出此预检请求:
OPTIONS http://myserver.local:7000/api/order/4 HTTP/1.1
Host: myserver.local:7000
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-my-custom-header
Origin: http://localhost:5000
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
和我的 API returns:
HTTP/1.1 204 No Content
Date: Wed, 09 Mar 2022 12:52:50 GMT
Server: Kestrel
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT,DELETE
Access-Control-Allow-Origin: http://localhost:5000
Vary: Origin
请注意,服务器允许在对预检请求的响应中使用方法 PUT
和 DELETE
,但不允许 POST
,这是实际 CORS 请求的方法。
浏览器是否应该因为实际请求的方法与Access-Control-Allow-Methods
header中列出的方法不匹配而阻止该请求?或者服务器以 [=19=] 状态代码响应浏览器接受预检然后发送实际请求就足够了吗?
我的假设是浏览器会比较 allow-methods 并在请求的方法不匹配时阻止请求...我是否遗漏了什么?
TL;DR
不,浏览器不要求服务器明确允许 POST
方法,因为后者作为 so-called CORS-safelisted method 获得免费通行证。
更多详情
规格说明
一如既往,答案在于 Fetch 标准 (section 4.8),它指定了 CORS 的工作方式:
- Let methods be the result of extracting header list values given
Access-Control-Allow-Methods
and response’s header list.
再往下:
- If request’s method is not in methods, request’s method is not a CORS-safelisted method, and request’s credentials mode is
"include"
or methods does not contain *
, then return a network error.
(我的重点)
什么是CORS-safelisted方法?该术语在 section 2.2.1:
中定义
A CORS-safelisted method is a method that is GET
, HEAD
, or POST
.
解读
如果 CORS 请求的方法是 GET
、HEAD
或 POST
之一,浏览器不要求服务器在 Access-Control-Allow-Methods
header CORS 预检成功。
实验
我在您的浏览器中发现 Jake Archibald's CORS playground useful for testing my (mis)understanding of CORS. Running this particular instance 可能会让您相信 POST
方法不需要明确允许 CORS 预检成功。
我认为我对 CORS 非常了解,但我仍然对浏览器在预检请求方面的行为感到困惑。
假设浏览器发出此预检请求:
OPTIONS http://myserver.local:7000/api/order/4 HTTP/1.1
Host: myserver.local:7000
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-my-custom-header
Origin: http://localhost:5000
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
和我的 API returns:
HTTP/1.1 204 No Content
Date: Wed, 09 Mar 2022 12:52:50 GMT
Server: Kestrel
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT,DELETE
Access-Control-Allow-Origin: http://localhost:5000
Vary: Origin
请注意,服务器允许在对预检请求的响应中使用方法 PUT
和 DELETE
,但不允许 POST
,这是实际 CORS 请求的方法。
浏览器是否应该因为实际请求的方法与Access-Control-Allow-Methods
header中列出的方法不匹配而阻止该请求?或者服务器以 [=19=] 状态代码响应浏览器接受预检然后发送实际请求就足够了吗?
我的假设是浏览器会比较 allow-methods 并在请求的方法不匹配时阻止请求...我是否遗漏了什么?
TL;DR
不,浏览器不要求服务器明确允许 POST
方法,因为后者作为 so-called CORS-safelisted method 获得免费通行证。
更多详情
规格说明
一如既往,答案在于 Fetch 标准 (section 4.8),它指定了 CORS 的工作方式:
- Let methods be the result of extracting header list values given
Access-Control-Allow-Methods
and response’s header list.
再往下:
- If request’s method is not in methods, request’s method is not a CORS-safelisted method, and request’s credentials mode is
"include"
or methods does not contain*
, then return a network error.
(我的重点)
什么是CORS-safelisted方法?该术语在 section 2.2.1:
中定义A CORS-safelisted method is a method that is
GET
,HEAD
, orPOST
.
解读
如果 CORS 请求的方法是 GET
、HEAD
或 POST
之一,浏览器不要求服务器在 Access-Control-Allow-Methods
header CORS 预检成功。
实验
我在您的浏览器中发现 Jake Archibald's CORS playground useful for testing my (mis)understanding of CORS. Running this particular instance 可能会让您相信 POST
方法不需要明确允许 CORS 预检成功。