C# HttpRequestMessage.GetClientCertificate()在Web API中返回null

C# HttpRequestMessage.GetClientCertificate()在Web API中返回null,c#,iis,asp.net-web-api,ssl-certificate,iis-express,C#,Iis,Asp.net Web Api,Ssl Certificate,Iis Express,我有一个.NET4.5 WebAPI 2应用程序,它使用SSL客户端证书进行一些自定义的安全相关检查 调试应用程序时,request.GetClientCertificate()对任何服务调用返回null,无论我目前尝试了什么 测试代码: 基本上,在我的服务方面,我有一个类似这样的方法: class CertificateChecker : ICertificateChecker { public bool Check(HttpRequestMessage request) {

我有一个.NET4.5 WebAPI 2应用程序,它使用SSL客户端证书进行一些自定义的安全相关检查

调试应用程序时,
request.GetClientCertificate()
对任何服务调用返回
null
,无论我目前尝试了什么

测试代码:

基本上,在我的服务方面,我有一个类似这样的方法:

class CertificateChecker : ICertificateChecker
{
    public bool Check(HttpRequestMessage request)
    {
        var cert = request.GetClientCertificate();
    }
}
使用
request.Properties.Add(HttpPropertyKeys.ClientCertificateKey,cert)
pass(证书完全按照预期生成,验证工作,等等),使用附加到请求的客户端证书进行单元测试

但是,当我使用一个调用实际WebAPI应用程序的
HttpClient
测试时,断点设置在服务端的
request.GetClientCertificate()
行,同一行返回null

以下是我尝试过的:

客户证书:

  • 创建了一个伪CA并将其放入可信CA存储(尝试了LocalMachine和当前用户)
  • 创建了由该伪造CA签名的客户端身份验证(1.3.6.1.5.5.7.3.2)证书,并将其放入个人存储(LocalMachine和当前用户)
(基本上,关注和类似的博客)

在我使用
HttpClient
调用服务的测试中,以以下方式附加客户端证书(所有方式均无效):

  • 使用
    WebRequestHandler
    ,将
    ClientCertificateOptions
    设置为手动,并将证书添加到
    ClientCertificates
    集合中

    using (var handler = new WebRequestHandler())
    {
         var cert = GetTestCert();
         handler.ClientCertificateOptions = ClientCertificateOption.Manual;
         handler.ClientCertificates.Add(cert);
    
         // and so on...
    }
    
  • 使用
    HttpRequestMessage
    ,将证书作为一个属性添加,并将密钥设置为
    HttpPropertyKeys.ClientCertificateKey
    (当进行如上所述的单元测试时,此方法有效)

在这两种情况下,
cert
变量都设置为预期的
X509Certificate2
对象

托管:

  • IISExpress:尝试在IISExpress中运行应用程序

    已编辑applicationhost.config,启用了
    iisClientCertificateMappingAuthentication
    并将以下访问设置设置设置为“true”(均无效):

    
    
  • 本地IIS 将web应用设置为在本地计算机上的IIS中运行

    • IIS中的站点配置了使用受信任证书的HTTPS绑定
    • 配置为使用https协议并启用IIS客户端证书映射身份验证的Web应用
    • 尝试了两种访问选项组合(
      Ssl、SslNegotiateCert
      SslNegotiateCert
      )(通过配置编辑器)

在这两种情况下,当使用web浏览器通过https url访问web api时,我会显示主控制器的索引视图而不会出现问题(因此,服务器端证书是可信的)。

关于您的问题的详细信息

我将假设问题在于附加客户端证书w/HttpClient,因为在这种情况下,您无法在服务器端查看证书。所有的主机和服务器端证书配置听起来都不错

  • 我会确保您附加的
    X509Certificate2 cert
    变量是存在于本地证书存储中的公钥(我不确定您将其存储在哪个存储位置)(您可以使用mmc.exe进行检查)。还要确保公钥带有私钥,因为HttpClient需要私钥来签署请求

  • 在代码片段中,在代码的其余部分之前,使用(var handler=new WebRequestHandler())。请确保您正在使用中构造
    HttpClient client=newhttpclient(handler)
    ,否则处理程序将被释放

  • 否则,处理程序的创建看起来不错


    祝你好运

    我知道这有点旧,但我也面临着同样的问题,我通过以下文章解决了这个问题:

    问题是IIS服务器上的配置,也可以在IIS express上修改该配置。我报告它的情况下,链接将不可用

    对于IIS,请更改服务器配置文件;对于IIS Express,请修改 解决方案下的文件位于中 .vs\config\applicationhost.config

    在元素内搜索名为的xml元素:

    <security>
      <access sslFlags="None" />
    
    
    
    默认配置不支持SSL客户端证书。 您需要修改sslFlags属性以包含以下选项: Ssl、SslNegotiateCert、SslRequireCert

    <security>
            <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />
    
    
    
    下一步是找到元素 :

    
    
    如果将enabled更改为true,IIS Express将开始接受客户端 证书:

    <iisClientCertificateMappingAuthentication enabled="true">
                </iisClientCertificateMappingAuthentication>
    
    
    
    现在需要重新启动Visual Studio和IIS Express。IIS Express can 使用系统托盘中的图标重新启动

    从现在起,将要求您提供客户端证书,您可以 在VisualStudio中调试整个应用程序。这看起来可能不太好 这是一个很大的改进,但是相信我,它使调试变得更加简单


    希望这能帮助其他人:-)

    感谢您的快速响应!我确实在存储中有证书的可导出私钥(它在使用
    HttpClient
    运行服务和测试的计算机上的个人存储中),并且我已经使用了HttpClient(handler)构造函数。我还尝试从pfx(包括私钥)获取相同的证书,但得到了相同的结果(正确的证书被实例化,但从未到达服务器端)。服务器是否知道需要什么类型的客户端凭据?通常我使用
    HttpSelfHostConfiguration config=newhttpselfhostconfiguration(hostAddres)
    config.ClientCredentialType=HttpClientCredentialType.Certificate
    <security>
            <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />
    
    <iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
    
    <iisClientCertificateMappingAuthentication enabled="true">
                </iisClientCertificateMappingAuthentication>