2010-12-04 31 views
9

私は先週、この爆発したWCFサービスの設定に苦労していました。私がやろうとしていることが、 、ドキュメントにもかかわらず。HTTPSを介したクライアント証明書によるWCFリクエストの認証

単純に、WCFサービスにクライアント証明書(サーバーが証明書ストアに保持する)を必要とし、System.ServiceModel.ServiceSecurityContextを使用してそのIDにアクセスしたいとします。さらに、これはトランスポートセキュリティを使用する必要があります。

<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には何もありません。私はこれらすべての要素について数十種類のバリエーションを試してきましたが、要求が「リモートホストによって強制的に既存の接続が強制的にクローズされました」という例外がスローされて必然的に終了します。

私は信頼できるCAストアにCA証明書を追加した自己署名証明書 "Cyber​​dyneIndustries"を使用しています。証明書は私がそれを見るときにチェックアウトする。私はhttp名前空間管理の地獄を通り抜けて、それらの問題を解決しました。 WCFがこれを本当にサポートしていないように見えます...私が間違っていると教えてください。

TIA。

答えて

2

最終的に、私はメッセージセキュリティを試して、それが状況を明らかにしているかどうかを確認することにしました。それはそうでした。私は損失を減らし、それに行くつもりです。だから、これには決定的な答えはありません。

しかし、メッセージセキュリティを実装すると大きな問題が発生し、これがトランスポートセキュリティの問題の根幹になっている可能性があります。 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

引数 "signature"は、代わりに "exchange"でなければなりません。すべての証明書を再生成すると、メッセージのセキュリティが働き始めました。このすべてからの大きな利点の1つは、トランスポートセキュリティを実装したい場合は、システムから取得するエラーメッセージがはっきりしているため、まずメッセージセキュリティが機能することです。私はこれが3歳、まだ興味があるかもしれない人のために知って

0

WsHttpBindingは、トランスポートセキュリティのための証明書認証をサポートしていません。

間違っているいくつかのことがある場合もあります。

  1. があなたの店に両方証明書を追加しましたか? Cyber​​dyneIndustriesだけでなく、あなたが署名に使用したCA? CAは「信頼されたルート証明機関」に属している必要があります。

  2. また、私はこれを自己完結型で実行しました。少なくともIISでサービスをホストしてみてください。 VS Devサーバーが証明書をサポートしているかどうかはわかりません。

  3. サービス認証を無効にしてください。したがって、クライアントはサービスを認証する必要はありません。アプリでこれをしたいかどうかは分かりませんが、単にテストのために私たちは、SSLハンドシェイクが成功してい

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

1

それを排除することができますか? SChannelロギングを有効にして、SSLレイヤのトラブルシューティングを行います。この古いKBの記事:How to enable Schannel event logging in IISを参照してください。 W2KとXP用のKBはありますが、SChannelロギングを有効にする手順は同じで、新しいシステムでも有効です。ロギングを有効にすると、なぜSSLが証明書を拒否しているのかを判断できるようになります。

1

...

私はWCF(他のものの間のセキュリティを)学習の過程でだと正常に動作し、物事を取得することができましたclientCredentialType = "Certificate"(そして、protectionLevel = "EncryptAndSign"というトランスポートセキュリティモードを使用すると、netTcpBinding(おそらく、これはWsHttpBindingsでも同様に動作します)。

私はサーバー側からも強制接続のクローズエラーが発生しましたが、1つの設定が欠落していることを発見しました。それはすべて今働いている。ここで

は私のサーバー側の設定です:

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

私は、サーバーの証明書チェーン(自己署名信頼されたルート証明書+証明書を作成しましたそのルートを使用して構築された)を使用して、ルート証明書と子証明書の両方を私のサーバーホストマシンの証明書ストアに保存しました。最後に、そのサーバー証明書+公開キーをクライアントホストマシンの証明書ストア(LocalMachine/TrustedPeople)にインポートしました。

関連する問題