尝试使用WCF客户端访问WSE服务时,意外地将SOAP正文粘贴在SOAP标头内



我正试图使用WCF访问WSE安全的web服务。我需要生成的SOAP头应该包含用户名、密码、nonce和创建日期。。。这里有一个soap UI头的例子,我用它来访问同一个服务。。。

   <soap:Header>
      <wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken wsu:Id="UsernameToken-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:Username>----------</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">----------</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Hozef94FFwOhuiF5QixaMQ==</wsse:Nonce>
            <wsu:Created>2012-08-21T13:26:03.642Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soap:Header>

现在我找到了一个非常有用的教程。使用完整教程

我已经成功地实现了它……但我现在将SOAP主体粘贴到SOAP头中,并且没有生成nonce。

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
    <s:Header>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo9VZylDHg5JMgjsNnWLhATkAAAAA+YtOxHdh0Uqd4a64raX/nIzYz20mPHlBv4Wk5S8d5PsACQAA</VsDebuggerCausalityData>
        <wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
            <UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                <Username>------------</Username>
                <Password>************</Password>
            </UsernameToken>
        </wsse:Security>
        <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <GetOrganizations xmlns="http://------------------------/businessobjects/messaging/">
                <personId xmlns="">0</personId>
                <typeId xmlns="">
                    <int>1</int>
                    <int>2</int>
                    <int>3</int>
                    <int>4</int>
                </typeId>
            </GetOrganizations>
        </s:Body>
    </s:Header>
</s:Envelope>

不知道它为什么这么做。我严格遵循了教程。我的存储库正在获取所有信息。。。

using (DistListServiceReference.DistributionListClient dlc = new DistListServiceReference.DistributionListClient())
            {
                try
                {
                    PasswordDigestBehavior behavior = new PasswordDigestBehavior("********", "********");                            
                    dlc.Endpoint.Behaviors.Add(behavior);
                    GetDistributionLists gdl = new GetDistributionLists();
                    gdl.PersonID = 0;
                    GetDistributionListsResponse gdlr = new GetDistributionListsResponse();
                    gdlr = dlc.GetDistributionLists(gdl);
                    return gdlr;
                }
                catch (Exception e)
                {
                    dlc.Abort();
                    return null;
                }
            }

我的密码DigentInspector

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            // Use the WSE 3.0 security token class
            UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendPlainText);
            WseHeader header = new WseHeader(this.Username, this.Password);
            // Serialize the token to XML
            XmlElement securityToken = token.GetXml(new XmlDocument());           
            MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);
            request.Headers.Add(header);
            // complete
            return Convert.DBNull;
        }

我如何应用客户行为

public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
        }

一切都在那里。我不知道尸体被注入头部的位置。有人有什么想法吗?

更新:调试我正在查看我注入到soap消息中的实际标头,这就是我所看到的。。。

{<wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <Username>**********</Username>
    <Password>************</Password>
  </UsernameToken>} System.ServiceModel.Channels.MessageHeaderInfo {TestDistListApplication.Repository.WseHeader}

仅从这个角度来看,没有nonce,我可以通过编程来构建它,但我不确定这是否是一个好主意。特别是因为securityToken中已经有一个nonce和一个创建日期。。。但不确定为什么它们没有出现在标题中。。。

<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MedTrak_Dev</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">uncJUN132012</wsse:Password>
<wsse:Nonce xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">mvy9nUfF+rnT3oTasDBqxg==</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2012-08-28T13:30:42Z</wsu:Created>

我已经停止了调试器,并且正在监视这两个变量。是什么原因导致标头没有这些东西,而WSEHeader有这些东西?看起来我必须调试它。

如果不亲自运行代码,就有点难以理解为什么我的示例在您的场景中不起作用。然而,在尝试调试时,我会尝试以下操作:

在这行上粘贴断点:

XmlElement securityToken = token.GetXml(new XmlDocument());

在完成这一行之后,看看securityTokenXML是什么样子的。正是这个XML被注入到安全头中。没有比这更复杂的了。如果需要,可以手动创建此XML。我使用WSE3.0类是因为我不想自己编写XML代码。

我还注意到,您的安全令牌定义与我的略有不同。我的例子是:

MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);

您的:

MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);

命名空间不同。有什么原因吗?

如果从上面的步骤添加的断点没有被命中,那么这将表明该行为实际上没有被应用。在这种情况下,您可能需要仔细检查您的配置,以确保行为正确应用于客户端。或者(如我的示例所示),您可以在发送消息之前通过程序添加自定义行为。

我建议任何处理WCF问题的人,首先打开详细的日志记录,然后使用fiddler来查看实际发生了什么。

最新更新