有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个wsdl,它定义了调用web服务时需要传递的soap头

示例SOAP头是:

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

CXF的wsdl2java生成了一个“AuthenticationInfo”java类,我可以创建该类并使用用户名和密码填充该类,但我不知道在调用web服务时如何将其传递给CXF客户端


共 (5) 个答案

  1. # 1 楼答案

    在使用Apache CXF生成代理类时,使用true添加extendedSoapHeaders将生成带有Request和Header参数的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>
    
  2. # 2 楼答案

    如果SOAP头是在WSDL中定义的,那么它可以被指定为implicit or explicit

    CXF提供了用于从WSDL生成Java服务接口的wsdl2java tool。对于显式标头,SOAP标头将自动检测并作为生成的服务接口的一部分提供

    如果SOAP头是隐式定义的,那么需要启用-exsh选项,该选项触发隐式SOAP头的处理。同样,SOAP头将作为生成的服务Java接口的一部分提供。如果你想要一个具体的例子,你可以查看我在how to add a cxf soap header上发表的一篇博文

    请注意,CXF还支持other ways of adding SOAP headers

  3. # 3 楼答案

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

    最后,获取您的请求上下文,并将此地图的arraylist添加为

    requestContext.put(MessageContext.HTTP_REQUEST_HEADERS,
    soapHeaders); 
    

    如果您试图传递自定义soap头,请参考THIS LINK

    THIS DISCUSSION中提到了一般的陷阱。这可能对你有帮助

  4. # 4 楼答案

    发现自己处于同样的情况:wsdl2java生成了header类,我需要将其作为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);
    
  5. # 5 楼答案

    使用CXF 3.4.4

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

    <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" );
        }
    }