我们运营可以从任何来源调用的公共API。为了允许调用,我们将所有CORS头设置为通配符,我们还设置了allow-credentials标头。
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Credentials: true
通常我们通过自定义HTTP标头进行身份验证,但对于一个特殊呼叫,我们也接受cookie。这背后的原因是我们通过API提供的文件下载。我们首先通过AJAX下载文件,显示进度指示器。作为此调用的一部分,我们将所有缓存标头设置为浏览器缓存中的文件。下载到浏览器缓存完成后,我们向指向我们刚刚预取的文件的页面添加一个隐藏的iframe。这样我们就可以强制浏览器正常下载"缓存中的文件。
如果某些浏览器缓存出错并且浏览器对API进行HTTP调用,我们希望将cookie设置为包含身份验证令牌的文件请求的一部分。这样,浏览器将在iframe中打开文件时发送cookie。这就是问题所在:您不能将Access-Control-Allow-Origin
标头设置为通配符,仍然使用withCredentials
设置。例如,Chrome会显示错误
XMLHttpRequest无法加载
https://myapihost/v1/file/1234
。回应 预检请求未通过访问控制检查:通配符'*
' 不能用于Access-Control-Allow-Origin
'标题时 凭证标志是真的。起源'http://myclientapp
'因此不是 允许访问。 XMLHttpRequest的凭据模式是 由withCredentials
属性控制。
有没有一些好方法来处理这种情况?我能想到的唯一解决方案是始终返回客户端在响应头中发送的原点。
我理解安全方面,一般来说,将资源打开到任何来源并不是一个好主意,但在我们的公共API的情况下,任何来源都可能有各种客户端应用程序。遗憾的是,打开iframe时无法告诉浏览器发送特定标头。
我目前还在考虑download.js下载预取文件,但在开始更大的返工之前,我想听听您的意见。