我有一个应用程序通过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“安全性 处理器无法找到 消息中的安全标头。这个 可能是因为消息是一个 无担保的错误或因为有一个 结合不匹配 沟通各方。这个可以 如果配置了服务,则会发生 安全性和客户端没有使用 安全“。
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服务以返回时间戳。
答案 0 :(得分:5)
虽然我发现您已经将Mark_S的答案标记为正确,但您可能会发现以下内容可以解决您的问题。
您的错误消息在Microsoft Hotfix KB971493中得到解决:.NET Framework 3.5 SP1提供了一个修补程序,该修补程序使WCF能够发送安全的消息并接收不安全的响应,并发送不安全的消息并接收安全的响应。
Windows Communication Foundation(WCF)无法发送安全邮件,然后接收不安全的响应,或发送不安全的邮件并接收安全响应。本文中介绍的修补程序添加了一个新的enableUnsecuredResponse属性。我很想知道这是否能解决您的问题。
答案 1 :(得分:3)
至于你的具体问题,请看一下Stackoverflow和其他地方的一些类似问题:
链接到有用的教程和屏幕演员,非常详细地解释了WCF:MSDN WCF Developer Center包含从初学者的教程到文章和示例代码的所有内容。
此外,我建议您查看Pluralsight screen casts on WCF - 这是一个很棒的系列,从“Creating your first WCF service”和“Creating your first WCF client”一直到相当高级的主题。 Aaron Skonnard在10-15分钟的截屏视频中很好地解释了所有内容 - 强烈推荐!