仅为特定路由或控制器需要 SSL 客户端证书

Require SSL Client Certificate only for specific routes or controllers

我有一个使用 Kestrel 作为服务器的 ASP.NET MVC 核心项目。它既提供用户内容 (asp.net mvc) 又托管与代理(软件)通信的网络 API 控制器。我启用了 HTTPS 和客户端证书支持。问题是我想要调用 Web APIs 的代理(软件)需要客户端证书,但我不想 require/prompt 用于基于浏览器的常规用户的客户端证书。

我已通过以下方式启用 HTTPS/client 证书支持:

var host = new WebHostBuilder()
.UseKestrel(options =>
{
    HttpsConnectionFilterOptions httpsoptions = new    HttpsConnectionFilterOptions();
    httpsoptions.ServerCertificate = CertUtil.GetServerCert();
    httpsoptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
    httpsoptions.CheckCertificateRevocation = false;

    options.UseHttps(httpsoptions);
})
.UseUrls("http://0.0.0.0:5000", "https://0.0.0.0:5001")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
host.Run();

我在 Startup.cs 中设置了一个单独的中间件处理程序来处理客户端证书的自定义验证。这段代码确实成功执行,从这个意义上说一切正常。

问题是这种情况在全球范围内发生,我只想将客户端证书应用于特定控制器 and/or 路由;或者我真的会在这一点上采取任何粒度。

本质上是尝试通过创建两个虚拟目录,然后将 SSL 设置设置为在一个上接受,在另一个上忽略,从而创建您可以在 IIS 中获得的相同类型的行为。带有 Accept 的将提示浏览器输入证书,而带有 Ignore 的则不会。

我尝试将 HttpsConnectionFilterOptions 设置为仅指定 ServerCertificate,希望不设置任何与客户端证书相关的选项将允许服务器在发送客户端证书时接收客户端证书,否则不会提示浏览器获取它们。这似乎不起作用,因为我的中间件客户端证书处理程序在调用此函数时从未看到客户端证书(当 ClientCertificateMode 设置为 AllowCertificate 时会看到。

context.Connection.GetClientCertificateAsync();

简而言之,我想 Kestrel 托管甚至允许更精细的客户端证书 mapping/handling 还是只能使用 IIS? IIS 不是该项目的选项,我宁愿不必为客户端证书 api 方面创建单独的 project/process。感谢任何帮助!

我遇到了与 context.Connection.GetClientCertificateAsync(); 相同的问题,它总是返回 null。然后我注意到我一直是 运行 Kestrel 通过 IIS Express。

因此,在 Visual Studio 中,我从调试器工具栏中将 IIS Express 更改为我的项目。 Kestrel 作为控制台应用程序启动,我能够获得客户端证书。

我认为 IIS Express 不支持客户端证书,所以证书总是被忽略。

对于问题的另一部分;我认为 Kestrel 不支持您在使用 HttpsConnectionFilterOptions 时开箱即用的这种粒度。从 Kestrel Connection Filter Options source code 如果客户端证书为空,连接将被断开。也许您可以修改 HttpsConnectionFilterOptions 的源代码并从中创建您自己的过滤器。然后您可以使用 ClientCertificateValidation 属性 指定自定义证书验证方法,在没有发送客户端证书时允许连接。

希望对您有所帮助。

我一直在尝试做同样的事情,和你的要求完全一样。

我得出的结论是这是不可能的。我的解决方法是使用 2 WebHostBuilder 对象 - 一个对象用于 不需要 的位置,另一个用于那些 。这确实有一个缺点,即每个 IWebHost 必须在不同的端口上侦听,但从你描述的场景来看,我想这不是一个大问题。

我在同一过程中执行此操作,因此此解决方案符合该要求。

我已经弄清楚如何只在某些路由上获得客户端证书,但是当 运行 在 Azure Web App 中时,客户端证书没有传递给代码。在 IIS Express 下 运行ning 也是同样的问题。

在这个例子中,一个控制器不需要证书,另外两个需要不同的证书。 https://github.com/xavierjohn/ClientCertificateMiddleware

如果在 IIS Express 下不是运行,证书确实会通过。

无需使用隔离的(新的)IWebHost 来控制对专用 MVC 控制器的访问。 为此,只需使用 MVC Filter