通过 SSL 进行 SOAP 纯文本密码身份验证的 WCF 配置
我有一个通过 https 连接到实现 WS-Security 的基于 SOAP 的 Web 服务的应用程序。 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“安全性 处理器无法找到 消息中的安全标头。这 可能是因为该消息是 不安全的故障或因为有 之间的结合不匹配 沟通各方。这个可以 如果服务配置为 安全且客户端未使用 安全。”
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 服务 。
如果有一种方法可以说服客户接受这种情况,我很想知道,同时我会研究是否可以将网络服务更改为 返回一个时间戳。
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.
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.
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>
and the client code looks like this:
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 "Security
processor was unable to find a
security header in the message. This
might be because the message is an
unsecured fault or because there is a
binding mismatch between the
communicating parties. This can
occur if the service is configured for
security and the client is not using
security."
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);
UPDATE:
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>
The client then throws an Exception
"Security processor was unable to find
a security header in the message. This
might be because the message is an
unsecured fault or because there is a
binding mismatch between the
communicating parties. This can
occur if the service is configured for
security and the client is not using
security."
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尽管我意识到您已经将 Mark_S 的答案标记为正确,但您可能会发现以下内容可以解决您的问题。
您的错误消息已在 Microsoft 修补程序 KB971493 中解决:该修补程序使 WCF 能够发送安全消息并.NET Framework 3.5 SP1 提供了接收不安全响应、发送不安全消息和接收安全响应的功能。
Windows Communication Foundation (WCF) 没有发送安全消息然后接收不安全响应的功能,或者发送不安全消息然后接收安全响应的功能。本文中描述的修补程序添加了新的enableUnsecuredResponse 属性。
我很想知道这是否能解决您的问题。
Although I realise that you have already marked the answer from Mark_S as correct, you may find the following resolves your issue.
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) 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.
至于您的具体问题,请查看 Stackoverflow 和其他地方的一些类似问题:
链接到有用的教程和屏幕截图,详细解释了 WCF:有 MSDN WCF 开发人员中心,其中包含从初学者教程到文章和示例代码的所有内容。
另外,我建议您查看 WCF 上的 Pluralsight 屏幕投射 - 这是一个出色的系列,来自“创建您的第一个 WCF 服务" 和 "创建您的第一个 WCF 客户端" 一直到相当高级的主题。 Aaron Skonnard 在 10-15 分钟的截屏视频中很好地解释了所有内容 - 强烈推荐!
As for your concrete problem, have a look at a few similar questions on Stackoverflow and elsewhere:
Links to useful tutorials and screen casts explaining WCF in great detail: there's the MSDN WCF Developer Center which has everything from beginner's tutorials to articles and sample code.
Also, I would recommend you have a look at the Pluralsight screen casts on WCF - it's an excellent series going from "Creating your first WCF service" and "Creating your first WCF client" all the way to rather advanced topics. Aaron Skonnard very nicely explains everything in 10-15 minutes screencasts - highly recommended!