繁体   English   中英

在CXF中如何将wsdl中定义的Soap Header添加到web服务客户端?

[英]How do you add a Soap Header defined in a wsdl to a web service client in CXF?

我有一个 wsdl 定义了一个 soap header 调用web服务时需要传递

样本 SOAP Header 为:

<soapenv:Header>
   <AuthenticationInfo>
      <userName>User</userName>
      <password/>
   </AuthenticationInfo>
</soapenv:Header>

CXF 的 wsdl2java 生成了一个“AuthenticationInfo”java class,我可以用用户名和密码创建并填充它,但我不知道在调用 web 服务时将其传递给 CXF 客户端的正确方法。

在使用 Apache CXF 生成代理类时,使用添加扩展的SoapHeaders 将生成带有请求和标题参数的 PortType 类。

<wsdlOption>              
<wsdl>${project.basedir}/src/main/resources/wsdl/sample.wsdl</wsdl>
 <!-- enables processing of implicit SOAP headers, default is false -->
<extendedSoapHeaders>true</extendedSoapHeaders>
</wsdlOption>

好吧,最简单的方法是创建一个Header对象的ArrayList并添加所有参数或Map<String,Object>并将所有标题添加为map.put("param1",param1).

最后获取您的请求上下文并将此地图数组列表添加为

requestContext.put(MessageContext.HTTP_REQUEST_HEADERS,
soapHeaders); 

如果您尝试传递自定义soap 标头,请参阅 此链接

本次讨论中已经提到了一般的陷阱。 它可能对你有帮助。

如果 SOAP 标头是在 WSDL 中定义的,那么它可以被指定为隐式或显式

CXF 提供了wsdl2java 工具,用于从 WSDL 生成 Java 服务接口。 在显式标头的情况下,SOAP 标头会被自动检测并作为生成的服务接口的一部分提供。

如果 SOAP 标头已被隐式定义,那么您需要启用-exsh选项以触发隐式 SOAP 标头的处理。 同样,SOAP 标头将作为生成的服务 Java 接口的一部分提供。 如果你想要一个具体的例子,你可以查看我写的一篇关于如何添加 cxf 肥皂头的博客文章。

请注意,CXF 还支持添加 SOAP 标头的其他方式

发现自己处于相同的情况: wsdl2java生成了标头类,我需要将它作为 SOAP 标头添加到传出的 SOAP 请求中。

我在代码中的解决方案如下(重用原始问题的AuthenticationInfo作为标题类名称):

import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.headers.Header;

AuthenticationInfo ai = new AuthenticationInfo();
ai.setUserName("User");
ai.setPassword("");

List<Header> soapHeaders = new ArrayList<Header>();

Header h1 = new Header(new QName("http://namespace/of/AuthenticationInfo", "AuthenticationInfo"), 
                       ai, new JAXBDataBinding(AuthenticationInfo.class));

soapHeaders.add(h1);

ClientProxy.getClient(port).getRequestContext().put(Header.HEADER_LIST, soapHeaders);

使用 CXF 3.4.4

您可以像这样添加一个 header 配置安全性

<soapenv:Header>
    <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
    <wsse:UsernameToken xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
    <wsse:Username>MY-USER</wsse:Username>
    <wsse:Password Type="wsse:PasswordText">MY-PWD</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>

使用拦截器,如下所述: http://cxf.apache.org/docs/ws-security.html

Client serviceClient = ClientProxy.getClient ( port );
        
Endpoint cxfEndpoint = serviceClient.getEndpoint ();
        
Map<String, Object> outProps = new HashMap<> ();
outProps.put ( WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN );
outProps.put ( WSHandlerConstants.USER, "MY-USER" );
outProps.put ( WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT );
outProps.put ( WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName () ); 
        
WSS4JOutInterceptor requestInterceptor = new WSS4JOutInterceptor ( outProps );
cxfEndpoint.getOutInterceptors ().add ( requestInterceptor );
    
MyRequest request = new MyRequest ();
    
Object [] res = serviceClient.invoke ( "operation-name", request );
MyResponse out = ( MyResponse ) res [0];

其中“operation-name”是要调用的 WebService 操作的名称

WSPasswordCallback 是:

import org.apache.wss4j.common.ext.WSPasswordCallback;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

public class ClientPasswordCallback implements CallbackHandler {

    public void handle ( Callback [] callbacks ) throws IOException, UnsupportedCallbackException {

        WSPasswordCallback passwordCallback = ( WSPasswordCallback ) callbacks [0];

        // Set the password for our message.
        passwordCallback.setPassword ( "MY-PWD" );
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM