向WSDL添加SOAP隐式头

向WSDL添加SOAP隐式头,soap,wsdl,soapheader,Soap,Wsdl,Soapheader,我的问题与此类似。但情况不同 对于我使用的web服务,所有方法都需要在SOAP头中以明文形式发送的身份验证。但是,我的WSDL不包含任何soap头信息。我有一个自定义的平台工具,我必须使用它从WSDL生成代码。由于标题信息不可用,我无法直接使用生成的类-我不想手动修改代码以适应标题 我尝试在WSDL中指定SOAP头,但未能获得正确的名称空间。WSDL在这里,SOAP头如下所示: <soapenv:Header> <wsse:Security>

我的问题与此类似。但情况不同

对于我使用的web服务,所有方法都需要在SOAP头中以明文形式发送的身份验证。但是,我的WSDL不包含任何soap头信息。我有一个自定义的平台工具,我必须使用它从WSDL生成代码。由于标题信息不可用,我无法直接使用生成的类-我不想手动修改代码以适应标题

我尝试在WSDL中指定SOAP头,但未能获得正确的名称空间。WSDL在这里,SOAP头如下所示:

    <soapenv:Header>
        <wsse:Security>
            <wsse:UsernameToken>
                <wsse:Username>username</wsse:Username>
                <wsse:Password>password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
   </soapenv:Header>

用户名
密码

有人能帮我吗?谢谢

从概念的角度来看,WSDL不应该定义头。WSDL仅用于定义服务的功能方面,如操作、消息、绑定和端点。消息和绑定定义了如何对消息的有效负载进行编码和格式化

但是,SOAP消息的头不属于有效负载。它们通常用于配置SOAP处理器的非功能属性。安全性就是这样一种非功能性属性。有效载荷的功能方面不受影响。只需确保通信是安全的,WS-tool堆栈(而不是服务实现)应该负责这一点

因此,缺少的部分现在是一个标准,它允许将一些非功能性需求附加到WSDL服务,这样代码生成器就可以自动派生出需要发送和/或理解哪些头,以便按照需要实现非功能性属性,而无需手动处理头字段。本标准存在,称为。策略通常包含一组备选方案,这些备选方案公开了提供者和使用者都应该能够满足的一组需求。当两个服务应该相互交互时,将采用两个策略并计算所谓的“有效策略”。它定义了常见的非功能性需求。使用此信息,提供者和使用者可以配置自己以添加所需的头,如WS-Security头。还定义了一组可以使用的策略。定义如何将此类策略附加到WSDL


有一些代码生成器可以处理WS-Policys,例如Metro或Axis2。您可以通过使用SoapHeader属性修饰从wsdl生成的代理类中的方法,将soap头信息添加到方法调用中

例如,当您“添加web引用”时,wsdl.exe将为web服务引用生成客户端代理类Reference.cs。在上面提到的链接中,有一条消息suggestAddress,当您从visual studio添加web引用时,该消息将转换为生成的reference.cs客户端代理代码文件中的方法。默认情况下,当调用此方法时,soap信封中将没有标头。要向此请求的信封中添加SoapHeader,请在Reference.cs生成的类中的SuggestAddress方法顶部添加[SoapHeader(“Security”)]属性,其中“Security”是从SoapHeader基类继承的类

对于上述必需的安全SoapHeader示例,您将创建以下类

public partial class Security : SoapHeader
{
    public UserNameToken UserNameToken { get; set; }
}

public partial class UserNameToken
{
    public string UserName { get; set; }
    public string Password { get; set; }
}
然后在reference.cs中修饰SuggestAddress方法,如下所示

[SoapHeader("Security")]
public suggestAddressesResult suggestAddresses([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] addressSearch search) {
        object[] results = this.Invoke("suggestAddresses", new object[] {search});
        return ((suggestAddressesResult)(results[0]));
    }
这将确保调用方法suggestAddress时创建的每个信封都包含一个类似于上面提到的安全标头

<soapenv:Header>
    <wsse:Security>
        <wsse:UsernameToken>
            <wsse:Username>username</wsse:Username>
            <wsse:Password>password</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>

用户名
密码

我用这个问题来帮助自己的关键是认识到(正如一些人指出的那样)问题中的头是WS-Security标准的头

如果您的代理生成工具是“自定义”的,那么您可能有一个开关来自动添加WS-Security的头,这似乎是合乎逻辑的。但是,如果您在VisualStudio中使用WSDLexe(“添加Web引用”),请考虑<代码> SvCuTIL.exe < /Cord>(“添加服务引用”)。< /P> 如果使用WCF代理,则可以覆盖给定的配置并允许WCF为您添加标题:

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

我不知道您的自定义工具是什么,但它所基于的框架可能也有类似的配置选项。

wsse
看起来像是WS-Security通常使用的前缀。此外,由于SOAP服务是自描述的,我无法找到WSDL中未定义头的有效原因。这是令人满意的。但正如我所说,我不想触及自动生成的类。我只是修改它来生成类。自动生成的类是部分类。也许您可以将标题添加到另一个类部分。当自动生成的文件再次生成时,它不会改变。header元素在wsdl/soap模式中定义,因此很难说不应该使用它:您当然可以使用WS-SecurityPolicy,但它只是一个不同的规范,尽管更具体。同意,对于绑定,WSDL如何将某些部分映射到SOAP头。但是,从概念的角度来看,我认为这是一个错误的做法,因为它将WSDL绑定到特定绑定。我同意,这个问题也是针对特定的SOAP绑定提出的,因此使用headers绑定可能很好,但使用WS-Policy是一个更合理的方法(即,它表达了非功能性的担忧“确保请求经过身份验证”而不是发送特定的头)。在前一种情况下,WS-stack已经知道该做什么了。虽然我仍然不同意这是“错误的做法”(日期可能是一个更好的评估),但我现在确实看到您在本例中指出WS-SecurityPolicy是正确的,因为OP中的头是WS-Security的头+1此处所指的建议地址是什么?我打不好。当弹劾
RemoteSvcProxy.TheirClient client = new RemoteSvcProxy.TheirClient();
client.ClientCredentials.UserName.UserName = "uname";
client.ClientCredentials.UserName.Password = "pwd";