![](/img/trans.png)
[英]CXF: Add implicit headers to WSDL and WADL responses for a CXF SOAP/REST web service
[英]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>
如果 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.