【问题标题】:Adding SOAP implicit headers to WSDL将 SOAP 隐式标头添加到 WSDL
【发布时间】:2011-08-09 05:27:36
【问题描述】:

我的问题与此类似。 How To Pass Soap Header When WSDL Doesn't Define It? 但不一样。

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

我尝试在 WSDL 中指定 SOAP 标头,但未能获得正确的名称空间。 WSDL 在这里https://stage.totalcheck.sensis.com.au/service/webservice?wsdl,SOAP 头如下:

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

有人可以帮助我吗?谢谢!

【问题讨论】:

  • wsse 看起来像通常用于 WS-Security 的前缀。此外,由于 SOAP 服务是自描述的,我无法找到 WSDL 中未定义的标头的正当理由。
  • 这很好。但就像我说的,我不想接触自动生成的类。我只是为了生成类而修改它。
  • 自动生成的类是部分类。也许您可以将标题添加到另一个类部分。再次生成自动生成的文件时不会改变。

标签: soap wsdl soapheader


【解决方案1】:

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

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

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

有一些代码生成器可以处理 WS-Policies,例如Metro 或 Axis2

【讨论】:

  • 标头元素在 wsdl/soap 模式中定义,因此很难说它不应该被使用:schemas.xmlsoap.org/wsdl/soap 您当然可以使用 WS-SecurityPolicy,但它只是一个不同的,尽管更具体的规范。
  • 同意,对于绑定,WSDL specifies 如何将某些部分映射到 SOAP 标头。但是,从概念的角度来看,我认为使用它是一种不好的做法,因为它将您的 WSDL 绑定到特定的绑定。我同意,这个问题也被问到特定的 SOAP 绑定,所以使用标头绑定可能很好,但使用 WS-Policy 是一种更合理的方法(即它表达了非功能性问题“确保请求是经过身份验证”与发送特定标头)。在前一种情况下,WS 堆栈已经知道要做什么。
  • 虽然我仍然不同意这是“不好的做法”(过时可能是更好的评估),但我现在确实看到您在这种情况下指向 WS-SecurityPolicy 是正确的,因为OP 是 WS-Security 的。 +1
【解决方案2】:

您可以通过使用 SoapHeader 属性装饰从 wsdl 生成的代理类中的方法,将肥皂头信息添加到方法调用中。

例如 wsdl.exe 将在您“添加 Web 引用”时为 Web 服务引用生成客户端代理类 Reference.cs。在上面提到的链接https://stage.totalcheck.sensis.com.au/service/webservice?wsdl 中有一条消息SuggestAddress,当您从Visual Studio 添加Web 引用时,该消息将转换为生成的reference.cs 客户端代理代码文件中的方法。默认情况下,调用此方法时,soap 信封中将没有 Header。要将 SoapHeader 添加到此请求的信封中,请将 [SoapHeader("Security")] 属性添加到 Reference.cs 生成的类中 SuggestAddress 方法的顶部,其中“Security”是继承自 SoapHeader 基类的类。

上述所需的 Security 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>

【讨论】:

  • 建议地址在这里指的是什么?我不能低调。在实施的同时,。我收到错误“SoapwbApp.withHeader”不包含“Invoke”的定义,并且找不到接受“SoapwbApp.withHeader”类型的第一个参数的扩展方法“Invoke”(您是否缺少 using 指令或程序集引用? )
  • 这是什么语言?
【解决方案3】:

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

如果您的代理生成工具是“自定义”的,那么您可能有一个开关来自动添加 WS-Security 的标头似乎是合乎逻辑的。但是,如果您使用 WSDL.exe(Visual Studio 中的“添加 Web 引用”),请考虑使用 svcutil.exe(“添加服务引用”)。

如果您使用 WCF 代理,您可以覆盖给定的配置并允许 WCF 为您添加标头:

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

您可以从那里指定密码:

RemoteSvcProxy.TheirClient client = new RemoteSvcProxy.TheirClient();
client.ClientCredentials.UserName.UserName = "uname";
client.ClientCredentials.UserName.Password = "pwd";

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 2013-01-29
    相关资源
    最近更新 更多