问题描述
我正在构建的网络应用程序出现问题.Web 应用程序由一个 Angular 4 前端和一个 dotnet core RESTful api 后端组成.要求之一是对后端的请求需要使用 SSL 相互认证进行认证;即客户端证书.
I'm having an issue with a web app I'm building. The web app consists of an angular 4 frontend and a dotnet core RESTful api backend. One of the requirements is that requests to the backend need to be authenticated using SSL mutual authentication; i.e., client certificates.
目前我将前端和后端都托管为 Azure 应用服务,它们位于不同的子域中.
Currently I'm hosting both the frontend and the backend as Azure app services and they are on separate subdomains.
按照本指南将后端设置为需要客户端证书,我认为这是为 Azure 应用服务执行此操作的唯一方法:https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth
The backend is set up to require client certificates by following this guide which I believe is the only way to do it for Azure app services:https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth
当前端向后端发出请求时,我将 withCredentials
设置为 true
— [根据文档][1],这也应该与客户端证书一起使用.
When the frontend makes requests to the backend, I set withCredentials
to true
— which, [according to the documentation][1], should also work with client certificates.
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 上,这是可行的,当发出请求时,浏览器会提示用户输入证书,它会包含在预检请求中,一切正常.
On Chrome this works, when a request is made the browser prompts the user for a certificate and it gets included in the preflight request and everything works.
对于所有其他主要浏览器,但情况并非如此.Firefox、Edge 和 Safari 都无法通过预检请求,因为当它们在请求中不包含客户端证书时服务器会关闭连接.
For all the other main browsers however this is not the case. Firefox, Edge and Safari all fail the preflight request because the server shuts the connection when they don't include a client certificate in the request.
直接浏览到 api 端点会使每个浏览器都提示用户输入证书,所以我很确定这与大多数浏览器如何处理带有客户端证书的预检请求明确相关.
Browsing directly to an api endpoint makes every browser prompt the user for a certificate, so I'm pretty sure this is explicitly relevant to how most browsers handle preflight requests with client certificates.
做错了什么?还是其他浏览器在发出请求时不提示输入证书而做错了?
Am doing something wrong? Or are the other browsers doing the wrong thing by not prompting for a certificate when making requests?
我需要支持 Chrome 以外的其他浏览器,所以我需要以某种方式解决这个问题.
I need to support other browsers than Chrome so I need to solve this somehow.
我已经看到通过让后端允许而不是要求证书来解决类似的问题.唯一的问题是我还没有找到一种方法来实际使用 Azure 应用程序服务来做到这一点.要么需要,要么不需要.
I've seen similar issues being solved by having the backend allow rather than require certificates. The only problem is that I haven't found a way to actually do that with Azure app services. It's either require or not require.
有人对我如何继续前进有任何建议吗?
Does anyone have any suggestions on how I can move on?
推荐答案
参见https://bugzilla.mozilla.org/show_bug.cgi?id=1019603 以及我在 CORS 与客户端 https 证书(我忘了我之前也看到过同样的问题报告……).
See https://bugzilla.mozilla.org/show_bug.cgi?id=1019603 and my comment in the answer at CORS with client https certificates (I had forgotten I’d seen this same problem reported before…).
总而言之,您所看到的差异的原因是 Chrome 中的一个错误.我已经在 https://bugs.chromium 提交了一个错误.org/p/chromium/issues/detail?id=775438.
The gist of all that is, the cause of the difference you’re seeing is a bug in Chrome. I’ve filed a bug for it at https://bugs.chromium.org/p/chromium/issues/detail?id=775438.
问题在于 Chrome 没有遵循规范要求,该规范要求浏览器不要在预检请求中发送 TLS 客户端证书;因此 Chrome 会在预检中发送您的 TLS 客户端证书.
The problem is that Chrome doesn’t follow the spec requirements on this, which mandate that the browser not send TLS client certificates in preflight requests; so Chrome instead does send your TLS client certificate in the preflight.
Firefox/Edge/Safari 遵循规范要求,不要在预检中发送 TLS 客户端证书.
Firefox/Edge/Safari follow the spec requirements and don’t send the TLS client cert in the preflight.
Given what’s shown in https://i.stack.imgur.com/GD8iG.png it’s hard to understand how this could actually be working as expected in Chrome — especially given that no browsers ever send credentials of any kind in the preflight requests, so any possible browsers differences in handling of credentials would make no difference as far as the preflight goes.
这篇关于为什么大多数浏览器的预检请求中不包含 TLS 客户端证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!