我的任务是创建一个将由外部客户端使用的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>
答案 0 :(得分:2)
您的绑定是basicHttpBinding
。您需要使用wsHttpBinding
。
答案 1 :(得分:0)
+1 @JohnSaunders因为他很可能在这里咆哮着正确的树。
您的客户端是.NET / WCF吗?如果没有,它可能没有实现WS-Security,或者至少不是WCF想要它的方式。
如果客户端是.NET,这只是客户端上不匹配的绑定。
mustUnderstand标志表示必须确认并处理WS-Security标头。非WS-Security客户端,无论是因为它不会说WS-Security还是未配置,都会忽略标头,尝试使用该消息并且服务器将会发挥作用。
您的另一个选择是在服务器上关闭拒绝。它将停止发送WS-Security标头。当然,那时你不会得到拒绝。
答案 2 :(得分:0)
我通过在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捕获原始soap请求/响应以比较差异,并查看为什么ClientCredentials不会导致“未被理解”错误,而生成的标头会出错。
另外,according to the MSDN文档,如果您只使用“Transport”,它将不知道使用WS-Security:“将此属性保留为其默认值,即System.ServiceModel.SecurityMode.Transport不使用WS-Security。“