具有证书客户端身份验证的自承载 WCF 服务Self-Hosted Wcf Service with Certificate client authentication

Self-Hosted Wcf Service with Certificate client authentication

提问人:Oleg Shraibshtein 提问时间:5/26/2019 最后编辑:Oleg Shraibshtein 更新时间:6/19/2019 访问量:1706

问:

我有一个自承载的 wcf 服务,它使用具有传输安全性的 wsHttpBinding。我希望该服务使用证书对客户端进行身份验证。

当客户端使用设置为“None”的 clientCredentialsType 与服务通信时,一切正常。 该证书是使用 OpenSSL(自签名)创建的,并在特定端口上向 netsh 注册。证书的名称是 DomainName(在我的情况下是计算机名称)。

更新
:我已为客户端和服务器创建了证书,并将它们放置在彼此的受信任根存储中(服务器证书在客户端的存储中,反之亦然)。

我在 SOF 上看过很多文章和其他问题,但即使是那些看起来相关的文章也无法帮助我解决问题。

当前配置

服务

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceBehavior">
          <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="httpsBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="01:00:00">
          <security mode="Transport" >
            <transport clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="serviceBehavior" name="Service">
        <endpoint binding="wsHttpBinding" bindingConfiguration="httpsBinding" contract="SomeNamespace.IService"/>
        <host>
          <baseAddresses>
            <add baseAddress="https://domain:port/Something/"/>
          </baseAddresses>
        </host>
      </service>
    </services>    
  </system.serviceModel>

客户

<system.serviceModel>  
    <client>  
      <endpoint address="https://domain:port/Something/"   
                behaviorConfiguration="endpointCredentialBehavior"  
                binding="wsHttpBinding"   
                bindingConfiguration="Binding"   
                contract="SomeNamespace.IService"/>  
    </client>  
    <behaviors>  
      <endpointBehaviors>  
        <behavior name="endpointCredentialBehavior">  
          <clientCredentials>  
            <clientCertificate findValue="DomainName"  
                               storeLocation="LocalMachine"  
                               storeName="My"  
                               x509FindType="FindBySubjectName" />  
          </clientCredentials>  
        </behavior>  
      </endpointBehaviors>  
    </behaviors>  
    <bindings>  
      <wsHttpBinding>         
        <binding name="Binding">  
          <security mode="Transport">  
            <transport clientCredentialType="Certificate"/>  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
  </system.serviceModel>  

我收到以下异常:

System.ServiceModel.Security.MessageSecurityException:客户端身份验证方案“匿名”禁止 HTTP 请求。---> System.Net.WebException:远程服务器返回错误:(403) 禁止访问。 在 System.Net.HttpWebRequest.GetResponse() 在 System.ServiceModel.Channels.HttpChannelFactory'1.HttpRequestChannel.HttpChannelRequest.WaitForReply (TimeSpan 超时)

.NET 安全 WCF 客户端

评论


答:

0赞 Abraham Qian 5/27/2019 #1

我们还需要做一件事。我们应该让他们的证书相互信任。服务器的证书必须受客户端信任,客户端的证书必须受服务器信任。
具体而言,服务器证书安装在客户端受信任的根证书颁发机构中,客户端证书安装在服务器受信任的根证书颁发机构中。最好使用本地计算机证书存储。我们可以使用 Certlm.msc 命令检查证书。
enter image description here有关此问题,请参阅官方文件。
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-certificate-authentication
对于其他特殊工具创建的一些特殊证书,比如 PowerShell,我们最好将项目的目标框架(服务器和客户端)设在 4.6.2 以上。

https://github.com/dotnet/docs/issues/12000 如果有什么我可以帮忙的,请随时告诉我。

评论

0赞 Oleg Shraibshtein 5/27/2019
感谢您的回复。我已经按照您的建议做了,但仍然没有用(我已经用这些信息更新了问题)。我还看了你推荐给我的文章,但仍然无济于事。你还有什么建议吗?
0赞 Abraham Qian 5/27/2019
在我使应用程序正常工作之前,我也得到了这个异常。是否已将 Everyone 帐户添加到证书私钥的管理组?此外,为什么客户端配置文件中没有“身份”部分?如果通过添加服务引用来调用服务,则配置文件会自动添加标识部分,如下所示。<identity> <dns value=“vabqia593VM”/> </identity> </endpoint>
0赞 Abraham Qian 5/27/2019
该值是服务器证书的公钥或服务器的计算机名称。
0赞 Oleg Shraibshtein 5/27/2019
能否指出将 Everyone 帐户添加到管理组的位置?
0赞 Oleg Shraibshtein 5/27/2019
我们的项目有一个通用的客户端基础结构,因为我们有多个不同的客户端连接到同一台服务器,并且我们使用 ClientBase 类手动发送请求。我将检查如何手动添加“身份”部分。
0赞 Davit Mikuchadze 6/19/2019 #2

您的配置文件看起来没问题。 我的第三方客户端证书(公钥)有同样的问题,无论我在哪里添加该证书仍然不起作用。 但是,我已经设法使它与我的自签名客户端证书一起使用。我只需要将客户端 CA 证书添加到服务器上的受信任根证书颁发机构。

我发现这两个主题有助于确定一些问题: 使用 IIS 承载的 WCF 进行相互身份验证 WCF – 使用证书的 2 路 SSL 安全性

希望对您有所帮助。如果我能设法解决这个问题,我会发布更新。

评论

0赞 Davit Mikuchadze 7/4/2019
我已经解决了第三方客户端证书(公钥)的问题,问题是由于测试我没有该证书的私钥,所以我的服务器无法验证客户端。此外,我还设法在 IIS 中正确启用证书映射(使用 Netsh 命令启用 DS 映射),并限制对未使用证书进行映射的所有用户的访问。我在 webconfig 中添加了授权,而不是在 IIS 中禁用匿名访问:<system.web> <authorization> <deny users=“?” /> </authorization> </system.web>