basicHttpBinding を使用して、SSL 経由で IIS 7 で WCF サービスを実行しています。これは、クライアントとサーバーの両方でバインディング タグがどのように見えるかです。
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService"
messageEncoding="Mtom"
transferMode="Buffered">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
サーバー側では、これは動作タグです。
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
すべて正常に動作します。
ここで、クライアントを認証するために証明書の資格情報タイプに切り替えたいのですが、ここで行き詰まっています。
私は次のことをしました:
- 現在のユーザーとローカル コンピューターの両方に対して、信頼されたルート証明機関にルート CA をインストールしました。
- 上記のルート CA の下に証明書を作成し、現在のユーザーとローカル コンピューターの個人用ストアにインストールしました。
- ここで説明されているように、IIS を実行しているマシン (実際には、私の開発マシンであるクライアントと同じマシンです) 上のローカル ユーザー間のマッピングを作成しました。
- system.webServer/security/access にある Web サイトの IIS 構成の SSL フラグは次のとおりです。 SslNegotiateCert (これがデフォルト)
- IIS で、Web サイトとアプリケーション用に「Accept」クライアント証明書を設定します (これらの設定は必要ですか?私の理解では、IIS は、WCF によってクライアントを認証するために使用されるこの証明書とは何の関係もありません)。
- アプリケーションの IIS のアプリケーション プールは、LocalService アカウントで実行されます。WinHttpCertCfg.exe ツールを使用して、ローカル マシン ストアにインストールされた証明書の LocalService へのアクセスを許可しました: WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "Jackson Michael" -a "LocalService"
クライアントとサーバーの両方のバインディング タグは次のようになります。
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService"
messageEncoding="Mtom"
transferMode="Buffered">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate" />
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
クライアントの場合:
<behaviors>
<endpointBehaviors>
<behavior name="clientCertificateEndpointBehavior">
<clientCredentials>
<clientCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindBySubjectName" findValue="Jackson Michael" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
サーバー側:
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
</behavior>
</behaviors>
クライアントは System.ServiceModel.Security.MessageSecurityException を受け取ります: 保護されていないか、または正しく保護されていない障害が相手から受信されました。障害コードと詳細については、内部の FaultException を参照してください。
Trace Viewer でトレース出力を調べると、次のようになります。
System.IdentityModel.Tokens.SecurityTokenValidationException: X.509 証明書 SN=Jackson、G=Michael、OID.2.5.4.41=Jackson Michael、E=michaeljackson5@jacksons.com、CN=Jackson Michael、C=LK チェーンの構築に失敗しました。使用された証明書には、検証できない信頼チェーンがあります。証明書を置き換えるか、certificateValidationMode を変更してください。証明書チェーンは正しく処理されましたが、CA 証明書の 1 つがポリシー プロバイダーによって信頼されていません。
serviceBehavior タグを編集して certificateValidationMode="None" を設定すると、同じ結果が得られます。
質問は次のとおりです。
- certificateValidationMode="None" が無視されるのはなぜですか?
- デフォルトの certificateValidationMode="ChainTrust" を使用して、または PeerOrChainTrust を使用して認証を機能させるために何が欠けていますか?
ありがとうございました。