Java 使用WSS4J(SOAP)在CXF Web服务中实现身份验证
我正在尝试在我的Web服务中使用用户名/密码实现身份验证。目前,我学习了CXF和如何配置东西,但就我的一生而言,我就是不能把我的头绕在安全部分上 我使用CXF从WSDL创建Java类。这是我对Web服务的XML配置Java 使用WSS4J(SOAP)在CXF Web服务中实现身份验证,java,web-services,soap,cxf,Java,Web Services,Soap,Cxf,我正在尝试在我的Web服务中使用用户名/密码实现身份验证。目前,我学习了CXF和如何配置东西,但就我的一生而言,我就是不能把我的头绕在安全部分上 我使用CXF从WSDL创建Java类。这是我对Web服务的XML配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="pacService" implementor="com.logicalprovisioning.internal.PacWS" address="/PacRequestSoapHttpPort">
<jaxws:properties>
<entry key="exceptionMessageCauseEnabled" value="true" />
<entry key="security.callback-handler" value="com.logicalprovisioning.webservices.clients.autheticate.AuthenticationCallback"/>
</jaxws:properties>
</jaxws:endpoint>
</beans>
目前这是一份草稿
我编写了一个客户端,用于初始化WebService(一个抽象类),并继承它以在不同的WebService中使用
public abstract class WebServiceClientBase implements HandlerResolver, SOAPHandler<SOAPMessageContext> {
protected int connectTimeout;
protected String endPointUrl;
protected String password;
protected String userName;
protected Logger logger = null;
private Service service = null;
public WebServiceClientBase () {
super();
}
public void init() {
// Set the security handler
getService().setHandlerResolver(new HandlerResolverImpl());
// Setting endpoint URL and timeout...
getBindingProvider().getRequestContext().put("javax.xml.ws.client.receiveTimeout", connectTimeout);
getBindingProvider().getRequestContext().put("javax.xml.ws.client.connectionTimeout", connectTimeout);
getBindingProvider().getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPointUrl);
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Content-Type", Collections.singletonList("application/soap+xml"));
headers.put(Message.ENCODING, Collections.singletonList("UTF-8"));
getBindingProvider().getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
}
@Override
@SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo arg0) {
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(this);
return handlerChain;
}
@Override
public boolean handleMessage(SOAPMessageContext soapMessageContext) {
if (!((Boolean) soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)). booleanValue()) {
return true;
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext arg0) {
return false;
}
@Override
public void close(MessageContext arg0) {
}
@Override
public Set<QName> getHeaders() {
return null;
}
protected Service getService() {
return service;
}
protected void setService(Service service) {
this.service = service;
}
protected abstract BindingProvider getBindingProvider();
}
公共抽象类WebServiceClientBase实现HandlerResolver、SOAPHandler{
受保护的int连接超时;
受保护的字符串端点URL;
受保护的字符串密码;
受保护的字符串用户名;
受保护的记录器=null;
私有服务=null;
公共WebServiceClient数据库(){
超级();
}
公共void init(){
//设置安全处理程序
getService().setHandlerResolver(新的HandlerResolverImpl());
//正在设置终结点URL和超时。。。
getBindingProvider().getRequestContext().put(“javax.xml.ws.client.receiveTimeout”,connectTimeout);
getBindingProvider().getRequestContext().put(“javax.xml.ws.client.connectionTimeout”,connectTimeout);
getBindingProvider().getRequestContext().put(BindingProvider.ENDPOINT\u ADDRESS\u属性,endPointUrl);
Map headers=newhashmap();
headers.put(“内容类型”,Collections.singletonList(“应用程序/soap+xml”);
headers.put(Message.ENCODING、Collections.singletonList(“UTF-8”));
getBindingProvider().getRequestContext().put(MessageContext.HTTP_请求_头,头);
}
@凌驾
@抑制警告(“原始类型”)
公共列表getHandlerChain(PortInfo arg0){
List handlerChain=new ArrayList();
handlerChain.add(这个);
返回手柄链;
}
@凌驾
公共布尔handleMessage(SOAPMessageContext SOAPMessageContext){
if(!((布尔)soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_属性)).booleanValue(){
返回true;
}
返回true;
}
@凌驾
公共布尔handleFault(SOAPMessageContext arg0){
返回false;
}
@凌驾
公共作废关闭(MessageContext arg0){
}
@凌驾
公共集getHeaders(){
返回null;
}
受保护的服务getService(){
回程服务;
}
受保护的无效设置服务(服务服务){
服务=服务;
}
受保护的抽象BindingProvider getBindingProvider();
}
我已经走了这么远了。我不确定如何将身份验证信息与webservice调用连接起来
任何指示都会有帮助。我一开始也在正确的轨道上吗?通过浏览所有教程和示例,我可能会陷入死胡同。假设com.logicalprovisioning.internal.PacWS是jaxws生成的PortType类,您可以这样做
...
com.logicalprovisioning.internal.PacWS pacWsPort = getService().get...Port();
org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(pacWSPort);
org.apache.cxf.endpoint.Endpoint endpoint = client.getEndpoint();
Map<String, Object> props = new HashMap<>();
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, AuthenticationCallback.class.getName());
props.put(WSHandlerConstants.USER, "TIM");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
endpoint.getOutInterceptors().add(wssOut);
// you can then call @WebMethod annotated methods on your PacWS object, and it should populate the wss-security soap header
。。。
com.logicalprovisioning.internal.PacWS pacWsPort=getService().get…Port();
org.apache.cxf.endpoint.Client Client=org.apache.cxf.frontend.ClientProxy.getClient(pacWSPort);
org.apache.cxf.endpoint.endpoint=client.getEndpoint();
Map props=newhashmap();
put(WSHandlerConstants.ACTION、WSHandlerConstants.USERNAME\u令牌);
put(WSHandlerConstants.PASSWORD\u类型,WSConstants.PW\u文本);
put(WSHandlerConstants.PW_CALLBACK_类,AuthenticationCallback.CLASS.getName());
props.put(wshandlerstants.USER,“TIM”);
WSS4JOutInterceptor wssOut=新WSS4JOutInterceptor(道具);
getOutiterCeptors().add(wssOut);
//然后可以在PacWS对象上调用@WebMethod注释的方法,它应该填充wss安全soap头
上面的一些代码可能可以替换为cxf xml配置文件中的配置
我不确定如何将身份验证信息与Web服务调用连接起来
您是在谈论基本身份验证还是与WS-Security相关的身份验证?WS-Security是我正在研究的。我读了这本指南,并查阅了其中的一些例子。但我还是没能下定决心。就我理解你的问题而言,你正在寻找一种方法将身份验证信息添加到你的客户端请求中?您可以尝试定义ws-security
属性和客户端回调处理程序,或者使用引用回调处理程序的WSS4JOutInterceptor
,如博客链接所示。我要试一试。我会回来的我会找到一些我不知道的东西understand@RomanVottner这两个链接很有帮助。我比以前走得更远了一点。但我一直停留在如何在由CXF wsdl2java创建的客户机上添加令牌/密码信息的方面。我发现的大多数示例都是从头开始编写的。
...
com.logicalprovisioning.internal.PacWS pacWsPort = getService().get...Port();
org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(pacWSPort);
org.apache.cxf.endpoint.Endpoint endpoint = client.getEndpoint();
Map<String, Object> props = new HashMap<>();
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, AuthenticationCallback.class.getName());
props.put(WSHandlerConstants.USER, "TIM");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
endpoint.getOutInterceptors().add(wssOut);
// you can then call @WebMethod annotated methods on your PacWS object, and it should populate the wss-security soap header