WCF 4 - TransportWithMessageCredential使用X.509证书进行传输和消息安全



我正在尝试创建一个托管在IIS上的WCF4服务,它将使用X.509证书来实现消息安全和SSL,并使用所需的相互认证来实现传输安全(项目规范要求使用WS-Security SSL, AFAIK通常只使用一个,但没关系)。

我制作了TestRootCA并使用它来颁发服务器证书(localhost)和客户端证书(TestUser)。我首先只想建立和测试传输安全性,所以我将IIS配置为使用https,配置SSL证书(我制作的本地主机证书),并将IIS配置为要求来自客户端的客户端证书。然后我修改了服务web。配置,制作相应的svcutil.conf并运行svcutil,成功地为我的测试WinForms应用程序制作客户端代理类和app.config。我在创建代理客户端时通过调用

设置证书:
var client = new ServiceClient();
client.ClientCredentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectDistinguishedName, "CN=TestUser");
MessageBox.Show(client.GetData(42));

到目前为止一切顺利。但是当我修改服务的网页时。配置使用transportwithmessagecredential(而不是Transport),并指定"证书"作为消息安全的clientCredentialType,我得到HTTP 403 - The HTTP request was forbidden with client authentication scheme 'Anonymous',即使我指定"证书"。

我的最后一张网。配置如下:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="wsHttpEndpointBinding">
                <security mode="TransportWithMessageCredential">
                    <transport clientCredentialType="Certificate"/>
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <services>
        <service behaviorConfiguration="serviceBehavior" name="Service">
            <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="IService" />
            <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="mexEndpoint" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="serviceBehavior">
                <serviceMetadata httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

和客户端app.conf:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
                <security mode="TransportWithMessageCredential">
                    <transport clientCredentialType="Certificate"/>
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" />
    </client>
</system.serviceModel>

任何想法?

编辑:

我已经设法通过更改IIS SSL设置的客户端证书从要求接受让它工作。当我在使用SSL的传输安全之上引入使用证书的消息安全性时,客户端使用证书进行消息签名,但使用而不是进行SSL的相互身份验证(它尝试以匿名身份登录,即使它已经分配了证书)。

不知道为什么会发生这种情况,我想听听专家的意见:)。

如问题所述,我通过将客户端证书的IIS SSL设置从require更改为accept来使其工作。然后,在服务入口点,我以编程方式检查远程用户的证书(如果它不是空的且有效)。

您必须在行为部分指定用于加密消息的证书,因为这些证书可能与用于建立https通道的证书不同

在服务器

中是这样的
<system.serviceModel> 
 <behaviors>     
    <serviceBehaviors>     
        <behavior name="serviceBehavior">
      <serviceCredentials>
        <serviceCertificate findValue="ServerCertificate"
                            storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindByIssuerName" />
        <clientCertificate>
          <certificate findValue ="ClientCertificate"
                       storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindByIssuerName"/>
          <authentication certificateValidationMode ="PeerTrust"/>
        </clientCertificate>
      </serviceCredentials>
            <serviceMetadata httpsGetEnabled="true" />     
            <serviceDebug includeExceptionDetailInFaults="true" />     
        </behavior>     
    </serviceBehaviors>     
</behaviors>   
</system.serviceModel> 

,在客户端做同样的操作,看起来像这样

<system.serviceModel>        
    <bindings>        
        <wsHttpBinding>        
            <binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">        
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />        
                <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />        
                <security mode="TransportWithMessageCredential">        
                    <transport clientCredentialType="Certificate"/>        
                    <message clientCredentialType="Certificate"/>        
                </security>        
            </binding>        
        </wsHttpBinding>        
    </bindings>
 <behaviors>      
  <endpointBehaviors>        
    <behavior name="ClientCredentialsBehavior">
      <clientCredentials>            
        <clientCertificate x509FindType="FindBySubjectName"
                           findValue="ClientCertificate"
                           storeLocation="CurrentUser"
                           storeName="My"/>
        <serviceCertificate>
          <defaultCertificate x509FindType="FindBySubjectName"
                              findValue="ServerCertificate"
                              storeLocation="CurrentUser"
                              storeName="My"/>
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>
    <client>        
        <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" behaviorConfiguration="ClientCredentialsBehavior" />        
    </client>        
</system.serviceModel>

当然,您必须在服务器和客户端设置正确的证书位置和名称。

我希望这仍然有帮助

相关内容

  • 没有找到相关文章

最新更新