我有一个应用程序,通过https连接到实现WS-Security的基于SOAP的Web服务。该Web服务是用Java编写的,需要明文密码以及正确设置的时间戳。
经过大量的谷歌搜索和尝试,我无法弄清如何配置我的WCF客户端与该服务交互。除了正确的答案外,我还希望能提供一个解释WCF和SOAP的教程链接。
我的当前客户端app.config如下:
这段代码抛出以下异常:
客户端会抛出异常。
"安全处理器无法在消息中找到安全头。这可能是因为消息是未经保护的故障,或者由于通信方之间存在绑定不匹配。如果服务配置了安全性而客户端未使用安全性,则可能会发生此情况。"
这似乎是因为客户端发送了时间戳标头,但服务没有返回时间戳标头。这可能是“正确的做法”,但并不是很有帮助,因为有许多Web服务部署在那里,期望有一个时间戳但却没有返回。
如果有办法说服客户端接受这种情况,我想知道。与此同时,我将研究是否可以更改Web服务以返回时间戳。
经过大量的谷歌搜索和尝试,我无法弄清如何配置我的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;
}
这段代码抛出以下异常:
WSE 3版本只需要以下代码即可运行:MessageSecurityException "安全处理器无法在消息中找到安全头。这可能是因为该消息是未安全保护的故障,或是通信双方之间存在绑定不匹配。如果服务配置了安全性而客户端未使用安全性,则可能会发生此情况。"
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>
客户端会抛出异常。
"安全处理器无法在消息中找到安全头。这可能是因为消息是未经保护的故障,或者由于通信方之间存在绑定不匹配。如果服务配置了安全性而客户端未使用安全性,则可能会发生此情况。"
这似乎是因为客户端发送了时间戳标头,但服务没有返回时间戳标头。这可能是“正确的做法”,但并不是很有帮助,因为有许多Web服务部署在那里,期望有一个时间戳但却没有返回。
如果有办法说服客户端接受这种情况,我想知道。与此同时,我将研究是否可以更改Web服务以返回时间戳。