7

我的任务是创建一个将由外部客户端使用的 WCF 服务。客户端正在使用 WSSE 安全性,具体来说,它们通过 SOAP 标头传递用户名令牌。

WCF 服务托管在启用了 SSL 的 IIS 服务器上。

在这一点上,我有一个半工作的原型。我现在要处理的问题是 SOAP 标头的 mustUnderstand 属性设置为 1,这会导致进程失败。

我想要一些关于如何处理用户名令牌的建议(或者更好的是,一个代码示例微笑),以便在 mustUnderstand 属性为 true 时返回正确的响应。

以下是失败的 SOAP 请求示例:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
       <soapenv:Header>
          <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken>
                <wsse:Username>TestUser</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPWD</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NzU3MjFhN2YtYTlmYS00ZWZjLTkxNjktY2ExZjlkZDEwNzE5</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2011-10-26T03:04:39Z</wsu:Created>
             </wsse:UsernameToken>
          </wsse:Security>
       </soapenv:Header>
       <soapenv:Body>
          <tem:Getstuff>
             <tem:Arg1>Arg1</tem:Arg1>
             <tem:Arg2>Arg2</tem:Arg2>
          </tem:Getstuff>
       </soapenv:Body>
    </soapenv:Envelope>

如果将soapenv:mustUnderstand="1" 更改为soapenv:mustUnderstand="0",则该过程有效。


PS:这是客户发送的修改后的示例请求:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Header>
        <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/WService/Getstuff</Action>
        <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="removed" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:Username>TestUser</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPass</wsse:Password>
            <wsse:Nonce>2Udx78sh2y2xRJYJpZZ9+w==</wsse:Nonce>
            <wsu:Created>2011-09-26T19:12:48Z</wsu:Created>
          </wsse:UsernameToken>
        </Security>
      </s:Header>
      <s:Body>
        <Getstuff xmlns="http://tempuri.org/">
         <Arg1>Arg1</Arg1>
         <Arg2>Arg2</Arg2>
        </Getstuff>
      </s:Body>
    </s:Envelope>

我收到对上述请求的以下回复:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
       <s:Body>
          <s:Fault>
             <faultcode>s:MustUnderstand</faultcode>
             <faultstring xml:lang="en-US">The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed.  This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process.  Please ensure that the configuration of the client's binding is consistent with the service's binding.</faultstring>
          </s:Fault>
       </s:Body>
    </s:Envelope>

这是绑定:

<bindings>
  <basicHttpBinding>
    <binding name="TransportBind" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
      maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <security mode="Transport">
        <transport clientCredentialType="None" />
      </security>
    </binding>
    <binding name="basic" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
      maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
    </binding>
  </basicHttpBinding>
</bindings>
4

3 回答 3

2

你的绑定是basicHttpBinding. 你需要使用wsHttpBinding.

于 2011-11-08T09:02:14.723 回答
1

我通过在 WCF 配置中不使用生成的 WS-Security 标头(当您添加服务引用时)解决了这个问题,而是将其注释掉,而是让 .NET 通过使用客户端凭据并指定安全模式来自行生成标头“TransportWithMessageCredential”:

client.ClientCredentials.UserName.UserName = "UserName";
client.ClientCredentials.UserName.Password = "Password";

<basicHttpBinding>
   <binding name="Binding">
      <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
          <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
   </binding>
</basicHttpBinding>

(我们使用的是 SSL,因此使用了这个安全设置)。

注释掉的生成标题:

 <client>
        <endpoint ...>
            <!--<headers>
                <wsse:Security...>
                </wsse:Security>
            </headers>-->
        </endpoint>
 </client>

不幸的是,我不知道足够的 WCF 来捕获原始肥皂请求/响应以比较差异并了解为什么 ClientCredentials 不会导致“不被理解”错误,而生成的标头会。

顺便说一句,根据 MSDN文档,如果您只使用“Transport”,它将不知道使用 WS-Security:“将此属性保留为其默认值,即 System.ServiceModel.SecurityMode.Transport 以不使用 WS -安全。”

于 2012-10-15T01:18:18.030 回答
0

+1 @JohnSaunders,因为他很可能在这里吠叫正确的树。

您的客户端是 .NET/WCF 吗?如果没有,它可能没有实现 WS-Security,或者至少不是 WCF 想要的方式。

如果客户端是 .NET,这只是客户端的不匹配绑定。

mustUnderstand 标志表示必须确认和处理 WS-Security 标头。非 WS-Security 客户端,无论是因为它不使用 WS-Security 还是未配置为,都将忽略标头,无论如何尝试使用该消息,服务器将取消。

您的另一个选择是在服务器上关闭拒绝。它将停止发送 WS-Security 标头。当然,这样你就不会被拒绝。

于 2011-11-07T23:30:17.990 回答