2010-12-04 148 views
9

過去一週我一直在爲這個被詛咒的WCF服務配置而苦苦掙扎,而且我開始懷疑我試圖做的事情是不可能的,儘管有文件。通過HTTPS客戶端證書驗證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> 

這裏是我的客戶端配置:

<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> 

代碼中所有工作完全在安全模式=「無」通過HTTP,當然,也沒有認證,而在System.ServiceModel.ServiceSecurityContext中什麼都沒有。我已經在所有這些元素上嘗試了數十種變體,並且所有這些都不可避免地導致請求拋出異常「現有連接被遠程主機強行關閉」。

我正在使用自簽名證書「​​Cyber​​dyneIndustries」,其CA證書已添加到受信任的CA商店。當我查看證書時,證書會被檢出。我經歷了http命名空間管理的難題,並解決了這些問題。它看起來像WCF並不真的支持這...請告訴我我錯了。

TIA。

回答

2

最終,我決定嘗試一下消息安全性,看看這是否會對情況有所瞭解 - 它的確如此,我將減少我的損失並繼續這樣做。所以,對此沒有明確的答案。

然而,實現消息安全確實暴露了BIG問題,這可能是傳輸安全問題的根源。有一個從MSDN一塊毒藥文檔:

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

在這個頁面上,以創建自簽名證書的命令如下:

makecert -sk MyKeyName -IV RootCaClientTest .pvk -n 「CN = tempClientcert」 -IC RootCaClientTest.cer -sr currentuser -ss我-sky簽名-pe

參數「簽名」應改爲「交換」。一旦我重新生成了所有證書,郵件安全就開始工作。從這一點來看,最重要的一點是,如果你想實現傳輸安全,首先要保證消息安全,因爲從系統獲得的錯誤消息更具描述性。

0

WsHttpBinding DOES支持傳輸安全的證書認證。

可以有幾件事情錯了:

  1. 你加證書來你的店? Cyber​​dyneIndustries以及您曾用於簽署的CA? CA應該位於「受信任的根證書頒發機構」

  2. 此外,我已經完成了這種自託管,從來沒有在Visual Studio Dev服務器中。嘗試至少在IIS中託管您的服務。我不確定VS Dev服務器是否支持證書。

  3. 嘗試關閉服務認證。所以客戶端不必認證服務。我不知道,如果你想這個應用程式或沒有,但只是爲了測試,所以我們可以排除這一可能性

    <behavior name="ClientCertificateBehavior"> 
    <clientCredentials> 
        <clientCertificate x509FindType="FindBySubjectName" findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" /> 
        <serviceCertificate> 
         <authentication certificateValidationMode="None"/> 
        </serviceCertificate> 
    </clientCredentials> 
    

1

是否SSL握手成功嗎?啓用S​​Channel日誌記錄以對SSL層進行故障排除。看到這個舊的知識庫文章:How to enable Schannel event logging in IIS。雖然是W2K和XP的KB,但啓用SChannel日誌的步驟相同,並且在較新的系統上仍然有效。啓用日誌記錄後,您將能夠確定SSL爲什麼拒絕該證書。

1

我知道這是3歲,但對於那些誰可能仍然有興趣...

我在學習WCF(除其他事項外安全)的過程中,能夠得到的東西正常工作與netTcpBinding(大概這也適用於WsHttpBindings),使用TransportCredentialType =「Certificate」(和,protectionLevel =「EncryptAndSign」,雖然這與問題沒有密切關係)的傳輸安全模式。

我確實遇到了來自服務器端的強制連接關閉錯誤,但發現我錯過了一個配置。現在都在工作。

這裏是我的服務器端配置:

<configuration> 
    <system.serviceModel> 
    <services> 
     <service name="MyNamespace.MyService" behaviorConfiguration="MyServiceBehavior"> 
     <endpoint address="net.tcp://localhost:9002/MyServer" binding="netTcpBinding" bindingConfiguration="TcpCertSecurity" contract="MyNamespace.IMyService" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="MyServiceBehavior"> 
      <serviceCredentials> 
      <serviceCertificate findValue="MyServiceCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> 
      <clientCertificate> 
       <authentication certificateValidationMode="PeerTrust"/> 
      </clientCertificate> 
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <netTcpBinding> 
     <binding name="TcpCertSecurity"> 
      <security mode="Transport"> 
      <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    </system.serviceModel> 
</configuration> 

而我的客戶端配置:

<configuration> 
    <system.serviceModel> 
    <client> 
     <endpoint address="net.tcp://localhost:9002/MyServer" binding="netTcpBinding" 
      bindingConfiguration="TcpCertSecurity" contract="MyNamespace.IMyService" 
      behaviorConfiguration="MyServiceBehavior"> 
     <identity> 
      <dns value="MyServiceCert" /> 
     </identity> 
     </endpoint> 
    </client> 
    <bindings> 
     <netTcpBinding> 
     <binding name="TcpCertSecurity"> 
      <security mode="Transport"> 
      <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="MyServiceBehavior"> 
      <clientCredentials> 
      <serviceCertificate> 
       <authentication certificateValidationMode="PeerTrust" /> 
      </serviceCertificate> 
      <clientCertificate findValue="MyServiceCert" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName" /> 
      </clientCredentials> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    </system.serviceModel> 
</configuration> 

我創建了一個證書鏈的服務器(自簽名的受信任的根證書+證書使用描述here描述的技術,並將Root證書和子證書存儲在我的服務器主機的證書存儲中。最後,我將該服務器證書+公鑰導入到我的客戶主機(位於LocalMachine/TrustedPeople)中的證書存儲中。