问题描述
我有一个应用程序,它通过 https 连接到实现 WS-Security 的基于 SOAP 的 Web 服务.Web 服务是用 Java 编写的,需要纯文本密码以及正确设置的时间戳.
I have an application that connects via https to a SOAP-based web service that implements WS-Security. The web service is written in Java, expects a plain text password as well as a properly set timestamp.
经过大量的谷歌搜索和实验后,我无法弄清楚如何配置我的 WCF 客户端以与此服务交互.除了正确的答案外,我还希望提供一个很好地解释 WCF 和 SOAP 的教程的链接.
After a great deal of googling and experimentation, I can't figure out how to configure my WCF client to interact with this service. In addition to a correct answer, I would also appreciate a link to a tutorial that explains WCF and SOAP well.
我当前客户端的 app.config 如下所示:
My current client's app.config looks like this:
<?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;
}
这段代码抛出了这个异常:
This code is throwing this exception:
MessageSecurityException "安全处理器无法找到消息中的安全标头.这个可能是因为消息是不安全的故障或因为有之间的绑定不匹配通信方.这个可以如果服务配置为安全性和客户端没有使用安全."
WSE 3 版本只需要以下内容即可工作:
The WSE 3 version simply requires the following to work:
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 中的此配置从服务器发回响应:
The request now reaches the server and a response is sent back from the server using this configuration in app.config:
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
客户端然后抛出异常
安全处理器无法找到消息中的安全标头.这个可能是因为消息是不安全的故障或因为有之间的绑定不匹配通信方.这个可以如果服务配置为安全性和客户端没有使用安全."
这似乎是因为客户端发送了 Timestamp 标头,但服务没有返回 Timestamp 标头.这可能是正确的做法",但它并不是很有帮助,因为部署了许多 Web 服务,它们期望时间戳但不返回时间戳.
This seems to be because the client sends a Timestamp header, but the service does not return a Timestamp header. This is probably "the right thing to do", but it's not very helpful because there are many web services deployed out there that expect a Timestamp but do not return one.
如果有办法说服客户接受这种情况,我很想知道.同时,我将研究是否可以将 Web 服务更改为返回时间戳.
If there is a way to convince the client to accept this situation I would love to know about it. In the mean time, I'll look into whether I can have the web service changed to return a Timestamp.
推荐答案
虽然我意识到您已经将 Mark_S 的答案标记为正确,但您可能会发现以下内容可以解决您的问题.
Although I realise that you have already marked the answer from Mark_S as correct, you may find the following resolves your issue.
您的错误消息在 Microsoft 修补程序 KB971493 中得到解决:使 WCF 能够发送的修补程序.NET Framework 3.5 SP1 提供安全消息和接收不安全响应以及发送不安全消息和接收安全响应.
Your error message is addressed in Microsoft Hotfix KB971493: A hotfix that enables WCF to send secured messages and to receive unsecured responses, and to send unsecured messages and to receive secured responses, is available for the .NET Framework 3.5 SP1.
Windows Communication Foundation (WCF) 没有发送安全消息然后接收不安全响应的功能,或者发送不安全消息并接收安全响应的功能.本文中描述的修补程序添加了一个新的 enableUnsecuredResponse 属性.
Windows Communication Foundation (WCF) does not have the functionality to send secured messages and then receive unsecured responses, or to send unsecured messages and receive secured responses. The hotfix that is described in this article adds a new enableUnsecuredResponse attribute.
我很想知道这是否能解决您的问题.
I would be interested to know if this solves your problem.
这篇关于通过 SSL 进行 SOAP 纯文本密码身份验证的 WCF 配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!