通过HTTPS通过客户端证书验证WCF请求

Chr*_*ens 9 ssl configuration wcf x509certificate transport-security

在过去的一周里,我一直在为这个爆破的WCF服务配置而苦苦挣扎,而且我开始怀疑我正在尝试做的事情是不可能的,尽管有文档.

很简单,我希望WCF服务需要客户端证书(服务器将在其证书存储中具有该证书),然后使用System.ServiceModel.ServiceSecurityContext访问该身份.此外,这需要使用传输安全性.

这是我的服务器配置:

<system.serviceModel>
    <services>
      <service behaviorConfiguration="requireCertificate" name="Server.CXPClient">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="PartnerComm.ContentXpert.Server.ICXPClient" />
        <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="mexEndpoint" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost:8371/Design_Time_Addresses/Server/CXPClient/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="requireCertificate">
          <serviceMetadata httpsGetEnabled="true" />
          <serviceCredentials>
            <serviceCertificate findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
            <clientCertificate>
              <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBinding" maxBufferPoolSize="5242880" maxReceivedMessageSize="5242880">
          <readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="1073741824" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

这是我的客户端配置:

  <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="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://localhost:8371/Design_Time_Addresses/Server/CXPClient/"
        binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" behaviorConfiguration="ClientCertificateBehavior"
        contract="ContentXPertServer.ICXPClient" name="wsHttpEndpoint" />
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <clientCredentials>
            <clientCertificate x509FindType="FindBySubjectName" findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" />
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

当http的安全模式='无'时,代码全部工作正常,但当然,没有身份验证,System.ServiceModel.ServiceSecurityContext中没有任何内容.我已经尝试了所有这些元素的几十种变体,并且所有这些都不可避免地导致请求抛出异常"现有连接被远程主机强行关闭".

我正在使用自签名证书"​​Cyber​​dyneIndustries",我已将CA证书添加到受信任的CA商店.我查看时证书会检出.我经历了http命名空间管理的地狱,并解决了这些问题.它看起来像WCF并不真正支持这个...请告诉我我错了.

TIA.

Chr*_*ens 2

最终,我决定尝试消息安全,看看这是否能对情况有所帮助——它确实如此,我将减少我的损失并接受它。所以,这个问题没有明确的答案。

然而,实现消息安全确实暴露了一个大问题,这可能是传输安全问题的根源。MSDN 上有一段有毒文档:

http://msdn.microsoft.com/en-us/library/ff650751.aspx

在此页面上,创建自签名证书的命令如下:

makecert -sk MyKeyName -iv RootCaClientTest.pvk -n "CN=tempClientcert" -ic RootCaClientTest.cer -sr 当前用户 -ss my -sky 签名 -pe

参数“签名”应该改为“交换”。一旦我重新生成了所有证书,消息安全性就开始工作。所有这一切的一个重要收获是,如果您想实现传输安全,请首先让消息安全发挥作用,因为从系统获得的错误消息更具描述性。