CORS 请求预检请求,以用户代码结尾
Posted
技术标签:
【中文标题】CORS 请求预检请求,以用户代码结尾【英文标题】:CORS request preflight request, ending in user code 【发布时间】:2015-08-20 03:01:25 【问题描述】:我有一组 WCF Web 服务在一个仅限内部的接口上运行,这些服务由许多其他网站调用(也仅限于内部)。域名匹配,只是端口号不同。
我正在向这些 Web 服务发出 AJAX POST 请求,因为它们在技术上不是同一个来源(不同的端口),所以我正在使用 CORS。
在 IE 中一切正常,(因为我相信 IE 不会将端口视为不同的来源)但是 Opera 和 Firefox 都会发送预检 OPTIONS 请求。
我已将 Web 服务配置为通过 web.config 文件接受这些请求:
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="*" />
我还在我的服务上设置了接口以接受任何 HTTP 动词:
[OperationContract(Name = "H2dbDataExport")]
[WebInvoke(Method = "*", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string H2dbDataExport(string action, string username, exportDetails data);
然而,这会导致底层服务被调用,并且由于它在 POST 请求回复中找不到任何期望的详细信息,并以标准的“您发送了一些错误”的响应。
如果我将服务更改为仅接受 POST 请求 - 这实际上是它会以任何相同方式响应的唯一响应:
[WebInvoke(Method = "POST", etc.......
然后预检 OPTIONS 得到“405 - Method not allowed”响应。
我做错了什么?我应该配置我的服务来回复 OPTIONS 请求吗?如果是,正确的回复是什么?
我假设我可以在服务中获取请求类型并回复 200 - 好的,如果动词是 OPTIONS 然后重新发送实际的 POST - 但如果我手动执行此操作,浏览器肯定会发送OPTIONS 再次作为它的新请求。
编辑:
我刚刚发现这篇文章,关于删除 WEBDAV 处理程序: CORS 405 (Method Not Allowed)
但这并没有帮助。
还有一篇关于将 OPTIONSHttpVerb 处理程序移至列表顶部并为其授予“读取”权限的帖子,但这也没有帮助。
编辑 2: 实际上移动 OPTIONSHttpVerb 确实有帮助,它不再调用 Web 服务,但 IIS 确实以 200 - OK 响应。然而,这个响应仍然会出现在浏览器的客户端代码中,所以没有任何帮助。
选项响应
HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/7.5
Public: OPTIONS, TRACE, GET, HEAD, POST
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Date: Fri, 05 Jun 2015 10:34:29 GMT
Content-Length: 0
【问题讨论】:
【参考方案1】:没有足够的业力来评论,所以我只是把它放在这里给像我一样来这个问题和回答的任何人,因为 IE11 在成功的 OPTIONS 请求(200 OK)后不会发送 POST 请求
它对我不起作用的原因是因为响应标头是大小写的,而请求标头不是,即:
请求标头:
Access-Control-Request-Headers: content-type, accept
响应标头:
Access-Control-Allow-Headers: Content-Type, Accept
这违反了 HTTP/1.1 标准 BTW,请参阅https://***.com/a/5259004/1602497
【讨论】:
【参考方案2】:看来都是我自己的错。 我将通配符用于:
<add name="Access-Control-Allow-Headers" value="*" />
这显然是不允许的。如果请求指定了 Access-Control-Request-Headers,那么服务器必须回复相同的列表。
https://***.com/a/13147554/1286358
http://www.html5rocks.com/en/tutorials/cors/
所以我只是检查了随 OPTIONS 请求发送的标头,并将其设置为被接受。
预检请求中有这一行:
Access-Control-Request-Headers: accept, content-type
所以我更改了 web.config 以匹配:
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="accept, content-type" />
现在它可以工作了。
这也让我可以将服务改回(正确地)只接受 POST 请求。
[WebInvoke(Method = "POST", etc.......
希望对其他人有所帮助。
【讨论】:
以上是关于CORS 请求预检请求,以用户代码结尾的主要内容,如果未能解决你的问题,请参考以下文章
cors跨域之简单请求与预检请求(发送请求头带令牌token)
使用 Django 和 Angular 的 CORS 预检请求