如何将CORS预检缓存应用于整个域

Min*_*ire 74 cors

我正在构建一个使用CORS的REST应用程序.每个REST调用都是不同的,我发现获得预检OPTIONS调用会有很大的开销.有没有办法缓存并应用预检OPTIONS结果,以便对同一域的任何后续调用都使用缓存的响应?

mon*_*sur 99

预检只能应用于请求,而不能应用于整个域.我在邮件列表上提出了同样的问题,并且存在安全问题.这是整个主题:http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html

如果您想限制预检请求的数量,有几件事需要考虑.首先请注意,基于WebKit/Blink的浏览器将最大预检缓存设置为10分钟:

https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/CrossOriginPreflightResultCache的.cpp

(我不确定其他浏览器是否适用).因此,虽然您应始终设置Access-Control-Max-Age标头,但最大值为10分钟.

接下来请注意,不可能避免对PUT/DELETE请求进行预检.因此,更新/删除API需要每10分钟至少进行一次预检.

在GET/POST上,尽可能避免使用自定义标题,因为这些仍会触发预检.如果您的API返回JSON,请注意"application/json"的Content-Type也会触发预检.

如果你愿意弯曲你的API是如何"RESTful"的,那么你可以尝试更多的东西.一种是使用不需要预检的Content-Type,例如'text/plain'.自定义标题始终会触发预检,因此如果您有任何自定义标题,则可以将它们移动到查询参数中.在最后,您可以使用JSON-RPC之类的协议,其中所有请求都发送到单个端点.

老实说,由于浏览器的预检缓存限制为10分钟,而REST的资源网址,预检缓存相当无用.在长时间运行的应用程序中,您无法限制预检.我希望CORS规范的作者将来会尝试解决这个问题.

  • @adaam应该做的伎俩.我刚刚在Firefox和Chrome中完成了一些测试,以便更好地理解行为,并且可以分享:如果您的自定义标头存在,浏览器将触发OPTIONS请求,除非存在"Access-Control-Max-Age"之前浏览器已经看到完全相同的URL,并且它在"Access-Control-Max-Age"指定的时间段内,并且所讨论的浏览器不会缩短值(Webkit,Firefox).如果您删除自定义标头,并将它们移动到网址,浏览器将不会发送OPTIONS请求.胜利! (4认同)
  • 缓存持续 10 分钟的事实已经过时了。从 v76 Chromium 开始允许两个小时。火狐浏览器 24 小时。认为应该在答案中更新,以便每个人都知道:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age (4认同)
  • @uglymunky我会澄清那一节.预检缓存的密钥基于origin/url对,其中url是完整的请求URL.我的意思是,如果你有一个自定义标题,即使在GET请求上也会触发预检.但是,如果将该自定义标头移动到查询参数中,则不会有GET/POST请求的预检. (3认同)
  • 在您的回答中,Content-Type限制仅在*发送*数据时相关,而不是在接收时,因此服务器返回任意内容类型标头时没有问题. (3认同)
  • @monsur派对迟到了,但是想知道你是否可以建议..我正在传递一个授权标题(例如"Basic [base64 encoded string]")以及对我的API的所有请求.预检请求主要阻碍了应用程序的性能.如果我要转移到基于令牌的身份验证系统(将令牌作为URL中的QS参数),并完全摆脱自定义标头,这将是一种避免可怕的OPTIONS请求GET和POST的方法(我'好吧,有一些PUT和DELETE)? (2认同)
  • 我喜欢他们刚刚停止回复您的电子邮件的方式。对于单个边缘情况,所有这些冗余调用。 (2认同)

Che*_*ewy 5

尝试使用xDomain

对于我来说,使用angular或jQuery进行设置非常简单。在您的应用服务器上,按照以下链接中的帮助所述添加proxy.html。在您的“客户端”和中提琴上添加一些引用js文件的标签,不再需要进行预检。它将包装在iframe中,以避免需要进行cors检查。

https://github.com/jpillora/xdomain