3

IIS でホストされる WCF4 サービスを作成しようとしています。これは、メッセージ セキュリティに X.509 証明書を使用し、トランスポート セキュリティに相互認証が必要な SSL を使用します (プロジェクトの仕様では、WS-Security と SSL の使用が必要です。通常、1 つだけが行きますが、気にしないでください)。

TestRootCA を作成し、それを使用してサーバー証明書 (localhost) とクライアント証明書 (TestUser) を発行しました。最初はトランスポート セキュリティのみを確立してテストしたかったので、https を使用するように IIS を構成し、SSL 証明書 (私が作成したローカルホスト証明書) を構成し、クライアントからのクライアント証明書を要求するように IIS を構成しました。次に、サービス web.config を変更し、対応する 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));

ここまでは順調ですね。しかし、サービスの web.config を (Transport の代わりに) TrasportWithMessageCredential を使用するように変更し、メッセージ セキュリティの clientCredentialType として "Certificate" を指定すると、"Certificate"HTTP 403 - The HTTP request was forbidden with client authentication scheme 'Anonymous'を指定したにもかかわらず、.

私の最終的な web.config は次のようになります。

<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 設定をrequireからacceptに変更することで、なんとか機能させることができました。SSL を使用したトランスポート セキュリティよりも証明書を使用したメッセージ セキュリティを導入すると、クライアントはメッセージの署名に証明書を使用しますが、SSL を介した相互認証には使用しないようです (証明書が割り当てられているにもかかわらず、匿名としてログオンしようとします)。

なぜこれが起こっているのかわからないので、専門家からのコメントが欲しいです:)。

4

2 に答える 2

2

質問で述べたように、クライアント証明書のIISSSL設定をからrequireに変更することで機能しましたaccept。次に、サービスエントリポイントで、リモートユーザーの証明書をプログラムでチェックします(nullでなく、有効でない場合)。

于 2012-07-20T08:17:07.990 に答える
1

動作セクションでメッセージの暗号化に使用する証明書を指定する必要があります。これは、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>

もちろん、サーバーとクライアントで証明書の正しい場所と名前を設定する必要があります。

これがまだ役立つことを願っています

于 2011-11-28T22:26:36.617 に答える