我有一组在仅限内部接口(interface)上运行的 WCF Web 服务,这些服务由许多其他网站(也仅限内部)调用。域名匹配,只是端口号不同。
我正在向这些 Web 服务发出 AJAX POST 请求,并且由于它们在技术上不是同一来源(不同的端口),因此我使用 CORS。
在 IE 中一切都很好(因为我相信 IE 不会将端口视为不同的来源),但是 Opera 和 Firefox 都会发送预检选项请求。
我已将 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="*" />
我还在我的服务上设置了接口(interface)以接受任何 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.......
然后,预检选项会收到“405 - 方法不允许”响应。
我做错了什么?我是否应该配置我的服务来回复 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
最佳答案
看来这都是我自己的错。 我使用通配符:
<add name="Access-Control-Allow-Headers" value="*" />
这显然是不允许的。如果请求指定了 Access-Control-Request-Headers,则服务器必须使用相同的列表进行回复。
https://stackoverflow.com/a/13147554/1286358
http://www.html5rocks.com/en/tutorials/cors/
因此,我只是检查了随 OPTIONS 请求发送的 header ,并将其设置为接受。
预检请求中有这一行:
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.......
希望对其他人有帮助。
关于http - CORS请求预检请求,以用户代码结尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30661819/