为什么浏览器允许 xorigin POST 但不允许 PUT?
Why does the browser allow xorigin POST but not PUT?
考虑使用 XMLHttpRequest
.
的非常简单的示例
以下帖子正确(您可以在网络选项卡中看到它,或者将浏览器定向到 http://requestb.in/yckncpyc
),尽管它会向控制台打印警告
XMLHttpRequest cannot load http://requestb.in/yckncpyc. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
const method = "POST"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
当然可以。我明白了。我不明白的是,为什么仅将用于 PUT
的动词更改为完全不同的结果。发送的请求是 OPTIONS
预检请求并打印
XMLHttpRequest cannot load http://requestb.in/yckncpyc. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
const method = "PUT"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
为什么浏览器* 以不同方式对待这些?这似乎是为了安全而做的事情,但实际上没有任何意义,因为攻击者总是可以使用 POST 而不是 PUT。
那么这里的逻辑是什么?
- 在 Chrome 52、Safari 9.1.2
中尝试过
GET
、HEAD
和 POST
请求(有一些其他限制)可以 cross-origin 进行,无需额外的通信。无法检查响应,但允许请求。
其他任何事情都需要 preflight 请求来检查来自目标站点的 headers 以查看请求是否被允许。
这样设置的原因是 GET
、HEAD
和 POST
在历史上被浏览器允许作为 HTML 语义的自然组成部分。脚本和 CSS 的标签以及图像执行 GET 请求,表单执行 POST。因此,当引入 CORS 内容时,允许这些内容的前提是站点不再像 XHR 世界中那样容易受到简单请求的攻击,然后它们处于更简单的 non-XHR 世界中。
如此简单的请求是允许的,浏览器查看响应headers来决定是否允许cross-origin页面中的请求代码看到响应内容。对于其他请求,浏览器首先发送一个OPTIONS
请求来检查CORS响应headers。只有当看起来没问题时(也就是说,如果响应 headers 包含适当的 "yes that's OK" headers)才会允许 XHR 继续。
考虑使用 XMLHttpRequest
.
以下帖子正确(您可以在网络选项卡中看到它,或者将浏览器定向到 http://requestb.in/yckncpyc
),尽管它会向控制台打印警告
XMLHttpRequest cannot load http://requestb.in/yckncpyc. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
const method = "POST"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
当然可以。我明白了。我不明白的是,为什么仅将用于 PUT
的动词更改为完全不同的结果。发送的请求是 OPTIONS
预检请求并打印
XMLHttpRequest cannot load http://requestb.in/yckncpyc. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
const method = "PUT"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
为什么浏览器* 以不同方式对待这些?这似乎是为了安全而做的事情,但实际上没有任何意义,因为攻击者总是可以使用 POST 而不是 PUT。
那么这里的逻辑是什么?
- 在 Chrome 52、Safari 9.1.2 中尝试过
GET
、HEAD
和 POST
请求(有一些其他限制)可以 cross-origin 进行,无需额外的通信。无法检查响应,但允许请求。
其他任何事情都需要 preflight 请求来检查来自目标站点的 headers 以查看请求是否被允许。
这样设置的原因是 GET
、HEAD
和 POST
在历史上被浏览器允许作为 HTML 语义的自然组成部分。脚本和 CSS 的标签以及图像执行 GET 请求,表单执行 POST。因此,当引入 CORS 内容时,允许这些内容的前提是站点不再像 XHR 世界中那样容易受到简单请求的攻击,然后它们处于更简单的 non-XHR 世界中。
如此简单的请求是允许的,浏览器查看响应headers来决定是否允许cross-origin页面中的请求代码看到响应内容。对于其他请求,浏览器首先发送一个OPTIONS
请求来检查CORS响应headers。只有当看起来没问题时(也就是说,如果响应 headers 包含适当的 "yes that's OK" headers)才会允许 XHR 继续。