7

クライアントとサーバーの両方で証明書認証を使用して WCF サービスをセットアップしようとしています。私は地獄を通り抜け、考えられるすべてのエラーメッセージをループしています。

ここでの最終的な目的は、証明書を使用して両当事者を認証することです。すべてのクライアントに対して特定の証明書を発行する予定です。これにより、(うまくいけば) それらを区別できるようになります。

これまでのところ、次の構成ファイルがあります。

サーバー構成ファイル

<configuration>
    <system.serviceModel>
        <services>
            <service name="ServiceApiImplementation" behaviorConfiguration="myBehaviour">
                <host>
                    <baseAddresses><add baseAddress="http://localhost:9110/MyService"/></baseAddresses>
                </host>
                <endpoint address="" binding="wsHttpBinding" contract="IServiceAPI" bindingName="SOAP12Binding">
                    <identity>
                        <certificateReference findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/>
                    </identity>
                </endpoint>
            </service>
        </services>
        <bindings>
            <wsHttpBinding>
                <binding name="SOAP12Binding" receiveTimeout="00:02:00" closeTimeout="00:01:00" openTimeout="00:01:00" sendTimeout="00:01:00">
                    <security mode="Message">
                        <message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <behaviors>
            <serviceBehaviors>
                <behavior name="myBehaviour">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials>
                        <serviceCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                        <clientCertificate>
                            <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/>
                        </clientCertificate>
                    </serviceCredentials>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

クライアント構成ファイル

<system.serviceModel>
    <client>
        <endpoint address="http://localhost:9110/MyService" binding="wsHttpBinding" 
                  bindingConfiguration="SOAP12Binding_IServiceAPI" contract="IServiceAPI" 
                  behaviorConfiguration="behaviour1" name="SOAP12Binding_IServiceAPI">
            <identity>
                <!-- Value obtained when "Adding a Service Reference in visual studio" -->
                <certificate encodedValue="xxxxxxxxxxxxx" />
            </identity>
        </endpoint>
    </client>
    <behaviors>
        <endpointBehaviors>
            <behavior name="behaviour1">
                <clientCredentials>
                    <clientCertificate findValue="ClientCertificate" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
                    <serviceCertificate>
                        <defaultCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                        <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
                    </serviceCertificate>
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <wsHttpBinding>
            <binding name="SOAP12Binding_IServiceAPI">
                <security mode="Message">
                    <message clientCredentialType="Certificate"  negotiateServiceCredential="false" establishSecurityContext="false" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
</system.serviceModel>

クライアントとサーバーの両方に rootCA といくつかの証明書を生成し、適切なアクセス許可を与えてストアに配置しました (LocalMachine と CurrentUSer の両方を絶望から解放します)。私の知る限り、このビットは機能しています。

サービスを呼び出すときに問題が発生します。最新のエラーは次のとおりです。

保護されていない、または誤って保護された障害が相手から受信されました。障害コードと詳細については、内部の FaultException を参照してください。

メッセージを処理できませんでした。これは、アクション「http://tempuri.org/IServiceAPI/MyMethod」が正しくないか、メッセージに無効または期限切れのセキュリティ コンテキスト トークンが含まれているか、バインディング間に ismatch があるためである可能性があります。非アクティブのためにサービスがチャネルを中止した場合、セキュリティ コンテキスト トークンは無効になります。サービスがアイドル セッションを途中で中止しないようにするには、サービス エンドポイントのバインディングで受信タイムアウトを早めに増やします。

または(前のエラー)

送信メッセージの ID チェックに失敗しました。期待される ID は 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn )' 'http://localhost:9110/MyService' ターゲット エンドポイントの場合。

エラー メッセージは、構成ファイルでの実験によって異なります。現在、クライアントとサーバーの両方が同じマシンで実行されているため、少なくとも、各アプリが rootCA を介して他のアプリを認証することを期待しています。

私は Message Security と wsHttpBinding を使用していることに注意してください。標準の JAVA フレームワークで使用できるサービスを公開することを除いて、大きな制限はありません。

この混乱を整理するのを手伝ってくれる人はいますか?

どんな助けでも大歓迎です

よろしく、

4

2 に答える 2

1

元の問題を解決することができました。

双方向の証明書認証に関しては、次の codeproject の記事で実際に動作するデモが提供されていることがわかりました。 on-WCF#Step%201:-%20Create%20client%20and%20server%20certificates

この例ではピア トラストを使用していることは確かですが、これまでのところ、動作するプロトタイプを何があっても動作させることはできませんでした。この時点から私が予想する唯一の落とし穴は、証明書チェーンを適切な場所に保存し、プロジェクトを実行しているユーザーに秘密鍵へのアクセスを許可することです。証明書の秘密キーにアクセス許可を付与する方法については、次の記事を参照してください: http://msdn.microsoft.com/en-us/library/ff647171.aspx#Step6

質問の 2 番目の部分: WCF サービスでクライアント証明書を区別する方法は? 、次のコードを使用して、クライアントの証明書の拇印を取得できます。

X509Certificate2 certificate = null;

if(ServiceSecurityContext.Current.AuthorizationContext.ClaimSets == null)
    throw new Exception("No claim set");

foreach(var claim in ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
    if(claim is X509CertificateClaimSet)
    {
        X509CertificateClaimSet xcset = claim as X509CertificateClaimSet;
        certificate = xcset.X509Certificate;
        break;
    }

if(certificate == null)
    throw new Exception("No X509 certificate found");

string clientCertificateThumbprint = certificate.Thumbprint;

これにより、証明書を発行するクライアントごとに異なるクライアントの拇印が取得されます。もちろん、他のすべての証明書データは利用可能です。

于 2012-09-08T01:45:45.460 に答える
0

メッセージを処理できませんでした。これは、アクション「http://tempuri.org/IServiceAPI/MyMethod」が正しくないか、メッセージに無効または期限切れのセキュリティ コンテキスト トークンが含まれているか、バインディング間に ismatch があるためである可能性があります。非アクティブのためにサービスがチャネルを中止した場合、セキュリティ コンテキスト トークンは無効になります。サービスがアイドル セッションを途中で中止しないようにするには、サービス エンドポイントのバインディングで受信タイムアウトを早めに増やします。

これは、サービス リクエストがタイムアウトしていることを示します。Windows イベント ビューアーを参照するか、サービスのログを有効にしてください。参照: http://msdn.microsoft.com/en-us/library/ms732023.aspx

送信メッセージの ID チェックに失敗しました。期待される ID は 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn )' 'http://localhost:9110/MyService' ターゲット エンドポイントの場合。

これは、indentityノードが誤って間違った場所を指していることを示しています。証明書を生成してから、サービスの場所を変更しましたか? 事後に引っ越した場合は無効です。

于 2012-08-23T17:21:37.930 に答える