正确方式传达SOAP Web服务的WSSE Usernametoken

|| 我正在尝试通过其相应的wsdl使用Web服务。此服务依赖于符合Web服务安全基本安全配置文件1.0的身份验证,包括http://docs.oasis-open.org/wss/2004/01/oasis-200401wss-wssecurity-secext-1.0的正确xmls命名空间。 xsd必须包含在请求中。 例:
<wsse:UsernameToken xmlns:wsse=\'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\' >
   <wsse:Username>
      Bob
   </wsse:Username>
   <wsse:Password Type=\'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\'>
      1234
   </wsse:Password>
</wsse:UsernameToken>
我的第一次尝试是针对thesdl并沿
Add Service Reference
进行,并使用它们
ServicePointManager.ServerCertificateValidationCallback = 
    (object s, X509Certificate certificate, X509Chain chain,
                     SslPolicyErrors sslPolicyErrors) => true;

var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = 
                                                HttpClientCredentialType.Basic;

var endpoint = new EndpointAddress(\"https://secure-ausomxana.crmondemand.com/...\"

using (var client = new ContactClient(basicHttpBinding, endpoint))
{

    var credential = client.ClientCredentials.UserName;
    credential.UserName = \"bob\";
    credential.Password = \"1234\";

    var input = ...    
    var output = client.ContactQueryPage(input);
}
但是,尝试用Fiddler询问SOAP消息时,我发现没有添加UsernameToken元素。 履行此合同的正确方法是什么? 编辑:根据来自@John Saunders的响应,我尝试更改我的代码以使用wsHttpBinding
var wsHttpBinding = new WSHttpBinding(SecurityMode.Transport);
wsHttpBinding.Security.Transport.ClientCredentialType =
                                         HttpClientCredentialType.Basic;
使用此绑定,SOAP消息变为
<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">
  <s:Header>
    <a:Action s:mustUnderstand=\"1\">document/urn:crmondemand/ws/ecbs/contact/10/2004:ContactQueryPage</a:Action>
    <a:MessageID>urn:uuid:17807f44-1fcasfdsfd</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand=\"1\">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
  </s:Header>
  <s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
    <ContactQueryPage_Input xmlns=\"urn:crmondemand/ws/ecbs/contact/10/2004\">
      <ListOfContact xmlns=\"urn:/crmondemand/xml/Contact/Query\">
        <Contact>
          <Id>1-asdfd</Id>
        </Contact>
      </ListOfContact>
    </ContactQueryPage_Input>
  </s:Body>
</s:Envelope>
这将添加Header元素,而不是用于引用使用BasicHttpBinding的原始肥皂消息的ѭ5元素。
<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
    <ContactQueryPage_Input xmlns=\"urn:crmondemand/ws/ecbs/contact/10/2004\">
      <ListOfContact xmlns=\"urn:/crmondemand/xml/Contact/Query\">
        <Contact>
          <Id>1-asdfds</Id>
        </Contact>
      </ListOfContact>
    </ContactQueryPage_Input>
  </s:Body>
</s:Envelope>
如果我将绑定更改为
var wsHttpBinding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
我得到的SOAP消息是
<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">
  <s:Header>
    <a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
    <a:MessageID>urn:uuid:eeb75457-f29e-4c65-b4bf-b580da26e0c5</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand=\"1\">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
    <o:Security xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" s:mustUnderstand=\"1\">
      <u:Timestamp u:Id=\"_0\">
        <u:Created>2011-05-02T13:30:09.360Z</u:Created>
        <u:Expires>2011-05-02T13:35:09.360Z</u:Expires>
      </u:Timestamp>
      <o:UsernameToken u:Id=\"uuid-dc3605a0-6878-42f4-b1f2-37d5c04ed7b4-2\">
        <o:Username>Bob</o:Username>
        <o:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">1234</o:Password>
      </o:UsernameToken>
    </o:Security>
  </s:Header>
  <s:Body>
    <t:RequestSecurityToken xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">
      <t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
      <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
      <t:Entropy>
        <t:BinarySecret u:Id=\"uuid-7195ad74-580b-4e52-9e2c-682e5a684345-1\" Type=\"http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce\">bI4xuyKwZ8OkQYBRnz2LDNV+zhIOnl0nwP24yI1QAwA=</t:BinarySecret>
      </t:Entropy>
      <t:KeySize>256</t:KeySize>
    </t:RequestSecurityToken>
  </s:Body>
</s:Envelope>
这似乎非常接近,但是实际上似乎已经加密了肥皂消息的正文,这是我不希望发生的事情。 如果我仅使用ѭ10来指定
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
,则返回到其匿名位置。 我无法解决的最后障碍是什么? 最终解决方案:弄清楚了,如果有帮助的人,我会发布此消息,这里的UserToken对象包装在Security节点中并没有什么不同,这是我的服务提供者所需要的,并且似乎是我的输出结果我可以生成的先前示例。
<system.serviceModel>
  <bindings>    
    <basicHttpBinding>
      <binding name=\"Contact\" closeTimeout=\"00:01:00\" openTimeout=\"00:01:00\"
          receiveTimeout=\"00:10:00\" sendTimeout=\"00:01:00\" allowCookies=\"false\"
          bypassProxyOnLocal=\"false\" hostNameComparisonMode=\"StrongWildcard\"
          maxBufferSize=\"524288\" maxBufferPoolSize=\"524288\" maxReceivedMessageSize=\"524288\"
          messageEncoding=\"Text\" textEncoding=\"utf-8\" transferMode=\"Buffered\"
          useDefaultWebProxy=\"true\">
        <readerQuotas maxDepth=\"32\" maxStringContentLength=\"65536\" maxArrayLength=\"131072\"
            maxBytesPerRead=\"32768\" maxNameTableCharCount=\"131072\" />
        <security mode=\"Transport\">
          <transport clientCredentialType=\"None\" proxyCredentialType=\"None\"
              realm=\"\" />
          <message clientCredentialType=\"UserName\" algorithmSuite=\"Default\" />
        </security>
      </binding>         
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address=\"https://secure-ausomxana.crmondemand.com/Services/Integration\"
       binding=\"basicHttpBinding\" bindingConfiguration=\"Contact\"
       contract=\"OnDemandContactService.Contact\" name=\"OnDemand.Contact.Endpoint\">
      <headers>        
        <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">
          <wsse:UsernameToken>
            <wsse:Username>USERNAME</wsse:Username>
            <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">PASSWORD</wsse:Password>
          </wsse:UsernameToken>
        </wsse:Security>
      </headers>
    </endpoint>
  </client>
</system.serviceModel>
请参阅使用C#,使用WSSE纯文本身份验证的WCF SOAP使用者?有关如何使用代码而不是config进行配置     
已邀请:
如果需要通过HTTPS发送用户名,则可以使用标准方法(如果正确定义了WSDL,则应该通过添加服务引用为您自动创建):
<bindings>
  <basicHttpBinding>
    <binding name=\"secured\">
      <security mode=\"TransportWithMessageCredential\">
        <message clientCredentialType=\"UserName\" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint name=\"...\" address=\"https://...\" contract=\"...\" binding=\"basicHttpBinding\"
            bindingConfiguration=\"secured\" />
</client>
您可以在代码中定义绑定:
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
basicHttpBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
您现在将在代理中设置凭据:
client.ClientCredentials.UserName.UserName = \"bob\";
client.ClientCredentials.UserName.Password = \"1234\";
如果只需要通过HTTP的UserNameToken配置文件,而没有任何其他WS-Security基础结构,则最简单的方法是使用ClearUserNameBinding。 如果您对来自客户端的所有请求都需要相同的用户名和密码,则可以使用简单的basicHttpBinding而没有任何安全性,并且可以包含来自配置的静态标头:
<client>
  <endpoint ...>
    <headers>
      <wsse:UsernameToken xmlns:wsse=\'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\' >
        <wsse:Username>Bob</wsse:Username>
        <wsse:Password Type=\'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\'>
           1234
        </wsse:Password>
      </wsse:UsernameToken>
    </headers>
  </endpoint>
</client> 
如果您需要更复杂的内容,请显示WSDL(安全性断言)的相关部分或示例SOAP请求。还要提及是否需要使用HTTP或HTTPS。     
@Ladislav的答案是正确的。但是,我尝试使用的SOAP 1.1 Web服务的价格为16美元。遵循Scott Hanselman的这篇博客文章之后,我得以实现它。这是我最终使用的代码:
    var oldBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
    oldBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
    //remove the timestamp
    BindingElementCollection elements = oldBinding.CreateBindingElements();
    elements.Find<SecurityBindingElement>().IncludeTimestamp = false;
    //sets the content type to application/soap+xml
    elements.Find<TextMessageEncodingBindingElement>().MessageVersion = MessageVersion.Soap11;
    CustomBinding newBinding = new CustomBinding(elements);
    
使用wsHttpBinding,而不是basicHttpBinding。 实际上,您应该只使用\“ Add Service Reference \”并指向该服务的WSDL。     

要回复问题请先登录注册