17

我的问题与此类似。WSDL 未定义时如何传递 Soap 标头?但不一样。

对于我使用的 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>

有人能帮我吗?谢谢!

4

3 回答 3

19

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

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

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

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

于 2011-04-21T08:41:38.580 回答
4

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

例如,当您“添加 Web 引用”时,wsdl.exe 将为 Web 服务引用生成客户端代理类 Reference.cs。在上面提到的链接https://stage.totalcheck.sensis.com.au/service/webservice?wsdl 中有一条消息SuggestAddress,当您添加一个网站时,它将转换为生成的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>

于 2012-10-06T04:45:53.277 回答
1

我使用这个问题来帮助自己的关键是认识到(正如一些人指出的那样)有问题的标头是 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";

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

于 2012-10-16T23:02:14.227 回答