我正在构建一个web api . 我发现每当我使用Chrome进行POST,GET到我的API时,总会在真实请求之前发送一个OPTION请求,这非常烦人 . 目前我让服务器忽略任何OPTIONS请求 . 现在我的问题是发送OPTION请求以加倍服务器负载是什么好事?有没有办法完全阻止浏览器发送OPTIONS请求?
15 回答
-2
花了整整一天半的时间试图解决类似的问题,我发现它与 IIS 有关 .
我的Web API项目设置如下:
// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
//...
}
web.config> system.webServer节点中的 I did not have CORS specific config options 就像我在很多帖子中看到过的那样
No CORS specific code in the global.asax or in the controller as a decorator
if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
set resp.http.Access-Control-Max-Age = "1728000";
set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
set resp.http.Content-Length = "0";
set resp.http.Content-Type = "text/plain charset=UTF-8";
set resp.status = 204;
}
15 回答
花了整整一天半的时间试图解决类似的问题,我发现它与 IIS 有关 .
我的Web API项目设置如下:
web.config> system.webServer节点中的 I did not have CORS specific config options 就像我在很多帖子中看到过的那样
No CORS specific code in the global.asax or in the controller as a decorator
问题是 app pool settings .
managed pipeline mode 设置为classic(将其更改为集成), Identity 设置为Network Service(将其更改为ApplicationPoolIdentity)
更改这些设置(并刷新应用程序池)为我修复了它 .
edit 2018-09-13 :增加了关于此飞行前请求的一些准确性以及如何在此响应结束时避免它 .
OPTIONS
请求是Cross-origin resource sharing (CORS)
中我们称之为pre-flight
的请求 .当您在特定情况下跨不同来源提出请求时,它们是必需的 .
某些浏览器将此飞行前请求作为安全措施,以确保服务器信任所完成的请求 . 这意味着服务器了解在请求上发送的方法,来源和标头是安全的 .
当您尝试执行跨源请求时,您的服务器不应忽略但处理这些请求 .
一个很好的资源可以在这里找到http://enable-cors.org/
处理这些以使其变得舒适的一种方法是确保对于具有
OPTIONS
方法的任何路径,服务器使用此标头发送响应Access-Control-Allow-Origin: *
这将告诉浏览器服务器愿意回答来自任何来源的请求 .
有关如何向服务器添加CORS支持的更多信息,请参阅以下流程图
http://www.html5rocks.com/static/images/cors_server_flowchart.png
edit 2018-09-13
CORS
OPTIONS
请求仅在某些情况下触发,如MDN docs中所述:请参考此答案,了解预先发出的OPTIONS请求的实际需求:CORS - What is the motivation behind introducing preflight requests?
要禁用OPTIONS请求,必须满足以下条件:ajax请求:
请求未设置自定义HTTP标头,如'application/xml'或'application/json'等
请求方法必须是GET,HEAD或POST之一 . 如果是POST,则内容类型应为
application/x-www-form-urlencoded
,multipart/form-data
或text/plain
之一参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
经历过这个问题,下面是我对这个问题和我的解决方案的结论 .
根据CORS strategy(强烈建议你阅读它)你不能强迫浏览器停止发送OPTION请求,如果认为它需要 .
有两种方法可以解决它
确保您的请求是"simple request"
为OPTION请求设置
Access-Control-Max-Age
简单请求
一个简单的跨站点请求是满足以下所有条件的请求:
唯一允许的方法是: - GET - HEAD - POST
除了由用户代理自动设置的 Headers (例如,连接,用户代理等)之外,允许手动设置的唯一 Headers 是: - 接受 - 接受 - 语言 - 内容 - 语言 - 内容类型
Content-Type标头唯一允许的值是: - application / x-www-form-urlencoded - multipart / form-data - text / plain
简单的请求不会导致飞行前的OPTION请求 .
为OPTION检查设置缓存
您可以为OPTION请求设置
Access-Control-Max-Age
,以便它在过期之前不会再次检查权限 .是的,可以避免选项请求 . 当您将任何数据发送(发布)到另一个域时,选项请求是预检请求 . 这是一个浏览器安全问题 . 但我们可以使用另一种技术:iframe传输层 . 我强烈建议您忘记任何CORS配置并使用现成的解决方案,它可以在任何地方使用 .
看看这里:https://github.com/jpillora/xdomain
工作示例:http://jpillora.com/xdomain/
祝你今天愉快!
当打开调试控制台并打开
Disable Cache
选项时,将始终发送预检请求(即在每个请求之前) . 如果您不禁用缓存,则只会发送一次飞行前请求(每台服务器)如前几篇文章中所述,
OPTIONS
请求是有原因的 . 如果您的服务器响应时间很长(例如海外连接),您也可以让浏览器缓存预检请求 .让您的服务器回复
Access-Control-Max-Age
标头,对于转到同一 endpoints 的请求,预检请求将被缓存而不再发生 .对于了解其存在的原因但需要访问不使用auth处理OPTIONS调用的API的开发人员,我需要一个临时答案,以便我可以在本地开发,直到API所有者添加适当的SPA CORS支持或我获得代理API启动并运行 .
我发现你可以在Safari上禁用CORS,在Mac上禁用Chrome .
Disable same origin policy in Chrome
Chrome:退出Chrome,打开终端并粘贴此命令:
open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Safari:Disabling same-origin policy in Safari
我已经解决了这个问题 .
它只是为了发展 . 有了这个我等待9ms和500ms而不是8s和500ms . 我可以这样做,因为 生产环境 JS应用程序将与 生产环境 在同一台机器上,所以没有
OPTIONS
但开发是我的本地 .你不能但是你可以使用JSONP来避免使用CORS .
对我有用的是导入“github.com/gorilla/handlers”,然后以这种方式使用它:
一旦我执行了Ajax POST请求并将JSON数据附加到它,Chrome就会始终添加Content-Type标头,这不在我以前的AllowedHeaders配置中 .
我想,您正在向 cross domain 发送请求 .
因此,您可能需要指定 contentType 以避免OPTION请求 .
Jquery示例: -
可能有一个解决方案(但我没有测试它):您可以使用CSP(内容安全策略)来启用您的远程域,浏览器可能会跳过CORS OPTIONS请求验证 .
如果找到一些时间,我会测试并更新这篇文章!
CSP:https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy
CSP规格:https://www.w3.org/TR/CSP/
我过去使用的一个解决方案 - 假设您的网站位于mydomain.com上,您需要向foreigndomain.com发出ajax请求
配置从您的域到外部域的IIS重写 - 例如
在你的mydomain.com网站上 - 然后你可以发出相同的原始请求,并且不需要任何选项请求:)
在使用拦截请求并写入适当头的代理的情况下,可以解决这个问题 . 在Varnish的特殊情况下,这些将是规则:
}