为什么大多数浏览器都没有将TLS客户端证书包含在预检请求中?

时间:2017-10-17 06:06:00

标签: angularjs azure ssl xmlhttprequest cors

我遇到了构建网页应用的问题。 Web应用程序由一个有角度的4前端和一个dotnet核心RESTful api后端组成。其中一个要求是需要使用SSL相互身份验证对后端的请求进行身份验证;即客户证书。

目前,我将前端和后端托管为Azure应用服务,并且它们位于不同的子域中。

后端设置为遵循本指南要求客户端证书,我认为这是为Azure应用服务执行此操作的唯一方法: https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth

当前端向后端发出请求时,我将true设置为const headers = new Headers({ 'Content-Type': 'application/json' }); const options = new RequestOptions({ headers, withCredentials: true }); let apiEndpoint = environment.secureApiEndpoint + '/api/transactions/stored-transactions/'; return this.authHttp.get(apiEndpoint, JSON.stringify(transactionSearchModel), options) .map((response: Response) => { return response.json(); }) .catch(this.handleErrorObservable); - [根据文档] [1],也应该使用客户端证书。

  

XMLHttpRequest.withCredentials属性是一个布尔值,指示是否应使用Cookie,授权标头或TLS客户端证书等凭据进行跨站点访问控制请求。设置withCredentials对同站点请求没有影响。

前端的相关代码:

{{1}}

在Chrome上,这是有效的,当发出请求时,浏览器会提示用户输入证书,并且它会包含在预检请求中,一切正常。

但对于所有其他主要浏览器,情况并非如此。 Firefox,Edge和Safari都会使预检请求失败,因为服务器在请求中不包含客户端证书时会关闭连接。

直接浏览到api端点会使每个浏览器都提示用户输入证书,因此我非常确定这与大多数浏览器如何使用客户端证书处理预检请求明确相关。

我做错了什么?或者其他浏览器是否通过在发出请求时不提示输入证书而做错了?

我需要支持除Chrome之外的其他浏览器,因此我需要以某种方式解决此问题。

我已经看到类似的问题通过后端允许而不是需要证书来解决。唯一的问题是我还没有找到一种方法来实现Azure应用服务。它要么需要也不要求。

有没有人对我如何继续前进有任何建议?

1 个答案:

答案 0 :(得分:4)

https://bugzilla.mozilla.org/show_bug.cgi?id=1019603的答案中查看CORS with client https certificates和我的评论(我忘记了之前我曾见过同样的问题......)。

所有这一切的要点,你所看到的差异的原因是Chrome中的一个错误。我在https://bugs.chromium.org/p/chromium/issues/detail?id=775438提交了一个错误。

问题是Chrome不符合规范要求,这要求浏览器不在预检请求中发送TLS客户端证书;所以Chrome改为 在预检中发送您的TLS客户端证书。

Firefox / Edge / Safari遵循规范要求,在预检中发送TLS客户端证书。

更新:在问题编辑中添加的Chrome屏幕截图显示OPTIONS请求GET请求以及后续GET请求 - 而不是{来自您的代码的{1}}请求。所以问题可能是服务器禁止POST请求。

https://i.stack.imgur.com/GD8iG.png中显示的请求是在您的代码中尝试POST请求之前浏览器自动发送的CORS preflight OPTIONS request

您的代码添加的POST请求标头会触发浏览器进行预检Content-Type: application/json请求。

了解浏览器永远不会在该预检OPTIONS请求中包含任何credentials非常重要 - 因此请求发送到的服务器必须配置为不需要任何凭据/身份验证{{1请求OPTIONS

但是,从https://i.stack.imgur.com/GD8iG.png开始,服务器似乎禁止向OPTIONS发出/api/transactions/own-transactions/次请求。也许这是因为请求缺少服务器期望的凭证,或者可能是因为服务器配置为禁止所有OPTIONS请求,无论如何。

因此,结果是,浏览器断定预检不成功,因此它会在那里停止,并且永远不会继续尝试代码中的/api/transactions/own-transactions/请求。

考虑到https://i.stack.imgur.com/GD8iG.png中显示的内容,很难理解这在Chrome中是如何实现预期的那样 - 特别是考虑到没有任何浏览器发送任何类型的credentials预检请求,因此在预检过程中,任何可能的浏览器在凭证处理方面的差异都没有区别。