通过SSL进行SOAP纯文本密码身份验证的WCF配置

Eri*_* J. 3 wcf ws-security soap

我有一个应用程序通过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>
Run Code Online (Sandbox Code Playgroud)

并且客户端代码如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)

此代码抛出此异常:

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);
Run Code Online (Sandbox Code Playgroud)

更新:

请求现在到达服务器,并在app.config中使用此配置从服务器发回响应:

<security mode="TransportWithMessageCredential">
  <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
  <message clientCredentialType="UserName" algorithmSuite="Default" />
</security> 
Run Code Online (Sandbox Code Playgroud)

然后客户端抛出异常

"安全处理器无法在消息中找到安全标头.这可能是因为消息是不安全的故障,或者因为通信方之间存在绑定不匹配.如果服务配置为安全性而客户端是没有使用安全性."

这似乎是因为客户端发送Timestamp标头,但该服务不返回Timestamp标头.这可能是"正确的事情",但它并不是非常有用,因为那里部署了许多期望时间戳但不返回时间戳的Web服务.

如果有办法说服客户接受这种情况,我很想知道.与此同时,我将研究是否可以更改Web服务以返回时间戳.

Reb*_*cca 5

虽然我意识到您已经将Mark_S的答案标记为正确,但您可能会发现以下内容可以解决您的问题.

您的错误消息在Microsoft Hotfix KB971493中得到解决:.NET Framework 3.5 SP1提供了一个修补程序,该修补程序使WCF能够发送安全的消息并接收不安全的响应,并发送不安全的消息并接收安全的响应.

Windows Communication Foundation(WCF)不具有发送安全消息然后接收不安全响应,或发送不安全消息并接收安全响应的功能.本文中介绍的修补程序添加了一个新的enableUnsecuredResponse属性.

我很想知道这是否能解决您的问题.