WS-Security を実装する SOAP ベースの Web サービスに https 経由で接続するアプリケーションがあります。Web サービスは Java で記述されており、プレーン テキストのパスワードと適切に設定されたタイムスタンプが必要です。
大量のグーグル検索と実験の後、このサービスと対話するように WCF クライアントを構成する方法がわかりません。正解に加えて、WCF と SOAP をよく説明しているチュートリアルへのリンクもいただければ幸いです。
現在のクライアントの app.config は次のようになります。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyServiceSoapBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
<!--security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security-->
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://p1.my.com/tx/services/MyService"
binding="basicHttpBinding" bindingConfiguration="MyServiceSoapBinding"
contract="My.IMyService" name="MyServiceEndpointPort" />
</client>
</system.serviceModel>
</configuration>
クライアントコードは次のようになります。
string response;
try
{
MyService.MyServiceClient svc = new WcfExample.MyService.MyServiceClient();
svc.ClientCredentials.UserName.UserName = "myUser";
svc.ClientCredentials.UserName.Password = "myPass";
response = svc.ping();
lblPingResponse.Text = response;
}
catch (System.ServiceModel.Security.MessageSecurityException mse)
{
lblPingResponse.Text = "MessageSecurityException: " + mse.Message;
}
catch (Exception ex)
{
lblPingResponse.Text = "Exception: " + ex.Message;
}
このコードはこの例外をスローしています:
MessageSecurityException "セキュリティ プロセッサは、メッセージ内のセキュリティ ヘッダーを見つけることができませんでした。これは、メッセージがセキュリティで保護されていない障害であるか、通信する当事者間にバインディングの不一致があるためである可能性があります。これは、サービスがセキュリティ用に構成されている場合に発生する可能性があります。セキュリティを使用していません。」
WSE 3 バージョンが機能するには、次のものが必要です。
ServiceUsernameTokenManager.AddUser(userName, password);
UsernameToken token = new UsernameToken(userName, password,
PasswordOption.SendPlainText);
proxy = new _MyServiceWse();
Policy policy = new Policy();
policy.Assertions.Add(new UsernameOverTransportAssertion());
policy.Assertions.Add(new RequireActionHeaderAssertion());
proxy.SetPolicy(policy);
proxy.SetClientCredential(token);
アップデート:
要求がサーバーに到達し、app.config の次の構成を使用してサーバーから応答が返されます。
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
その後、クライアントは例外をスローします
「セキュリティ プロセッサは、メッセージ内のセキュリティ ヘッダーを見つけることができませんでした。これは、メッセージがセキュリティで保護されていない障害であるか、通信する当事者間にバインディングの不一致があるためである可能性があります。これは、サービスがセキュリティ用に構成されていて、クライアントがセキュリティを使用していません。」
これは、クライアントが Timestamp ヘッダーを送信しているのに、サービスが Timestamp ヘッダーを返していないことが原因のようです。これはおそらく「正しいこと」ですが、タイムスタンプを期待しているが返さない Web サービスが数多く展開されているため、あまり役に立ちません。
クライアントにこの状況を受け入れるよう説得する方法があれば、ぜひ知りたいです。それまでの間、タイムスタンプを返すように Web サービスを変更できるかどうかを調べます。