一尘不染

为什么大多数浏览器的预检请求中不包括TLS客户端证书?

angularjs

我正在构建的Web应用程序有问题。该Web应用程序由一个angular 4前端和一个dotnet核心RESTful
API后端组成。要求之一是,需要使用SSL双向身份验证来验证对后端的请求。即客户证书。

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

遵循本指南将后端设置为要求客户端证书,我认为这是针对Azure应用程序服务的唯一方法:https :
//docs.microsoft.com/zh-cn/azure/app-service/app-
服务网络配置TLS相互认证

当前端向后端发出请求时,我设置withCredentialstrue- [根据文档] [1]也应与客户端证书一起使用。

XMLHttpRequest.withCredentials属性是一个布尔值,指示是否应使用cookie,授权标头或TLS客户端证书之类的凭据发出跨站点访问控制请求。设置withCredentials不会影响同一站点的请求。

前端的相关代码:

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);

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

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

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

做错什么了吗?还是其他浏览器通过发出请求时不提示输入证书来做错事?

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

我看到通过让后端允许而不是要求证书可以解决类似的问题。唯一的问题是,我还没有找到使用Azure应用程序服务实际执行此操作的方法。它是必需的还是不需要的。

有人对我的前进方式有任何建议吗?


阅读 309

收藏
2020-07-04

共1个答案

一尘不染

请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=1019603和我在CORS中使用客户端https证书的答案中的评论(我忘记了以前见过同样的问题……)。

要点是,您发现与众不同的原因是Chrome中的错误。我已经在https://bugs.chromium.org/p/chromium/issues/detail?id=775438上提交了一个错误。

问题在于Chrome浏览器未遵循此规范要求,该规范要求浏览器不要在预检请求中发送TLS客户端证书;因此Chrome
在飞行前发送您的TLS客户端证书。

Firefox / Edge / Safari遵循规范要求,并且 不要 在飞行前发送TLS客户端证书。


更新
:在对问题的修改中添加的Chrome屏幕截图显示了对OPTIONS请求的GET请求以及随后的请求,而GET不是POST代码中的请求。因此,问题可能出在服务器禁止POST请求。


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

Content-Type: application/json您的代码添加的请求标头是触发浏览器发出该预检OPTIONS请求的原因。

了解浏览器就不会包括任何这一点很重要凭据在预检OPTIONS所以服务器的请求被发送到必须被配置为不需要任何凭证/认证-
请求OPTIONS请求/api/transactions/own-transactions/

但是,从https://i.stack.imgur.com/GD8iG.png看来,服务器正在禁止对此OPTIONS请求/api/transactions/own- transactions/。可能是因为请求缺少服务器期望的凭据,或者是因为服务器配置为禁止所有OPTIONS请求,无论如何。

因此,结果是,浏览器认为预检不成功,因此它就在那里停止了,并且从不尝试POST从您的代码中尝试请求。

鉴于https://i.stack.imgur.com/GD8iG.png中显示的内容,很难理解它在Chrome中的实际效果如何-
尤其是考虑到没有浏览器在预检请求中曾经发送过任何形式的凭证,因此就预检而言,任何可能的浏览器在处理凭据方面的差异都不会造成任何影响。

2020-07-04