我正在尝试使用WS-Security UsernameToken规范1.0连接到Web服务, 使用apache cxf 2.4.0。
我从CXF文档中复制了以下代码,但是我得到了:org.apache.cxf.ws.policy.PolicyException:没有可用的用户名
MyService_Service ss = new MyService_Service(wsdlURL, SERVICE_NAME);
MyService port = ss.getBasicHttpBindingMyService ();
Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, "USERNAME");
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
ClientPasswordHandler.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
我还从文档中实现了一个ClientPasswordHandler类,但似乎永远不会发送用户名(根据错误)。 这是密码处理程序:
public class ClientPasswordHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword("Password");
}
}
有没有办法查看是否正在应用WSS4Jinterceptor,并且发送了UsernameToken?
答案 0 :(得分:19)
您是否在客户端获得PolicyException?如果是这样,这可能意味着您使用的WSDL中包含一个WS-SecucurityPolicy片段,该片段描述了它想要和期望的UsernameToken策略。如果是这种情况,则根本不应配置WSS4JOutInterceptor。 WS-Policy运行时将处理它,您只需提供它可能需要的一些属性。
SecurityPolicy内容的文档位于:http://cxf.apache.org/docs/ws-securitypolicy.html
您可能只需要使用:
Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "USERNAME");
ctx.put("ws-security.password", "Password");
答案 1 :(得分:1)
在使用Daniel的回答时,我得到了以下异常
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://..
at .apache.cxf.inorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1555)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1494)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1402)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:649)
at orgterceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:535)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:465)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:368)
我使用了以下内容并开始工作
Map ctx = ((BindingProvider) ssPort).getRequestContext();
ctx.put(BindingProvider.USERNAME_PROPERTY, "user");
ctx.put(BindingProvider.PASSWORD_PROPERTY, "pass");
ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://c
答案 2 :(得分:1)
感谢Daniel,我的完整工作配置如下:
webServicePort = webService_service.getPort(WebService.class);
Client client = ClientProxy.getClient(webServicePort);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String, Object> props = ((BindingProvider) webServicePort).getRequestContext();
props.put("ws-security.username", PravoRuConstants.USERNAME);
props.put("ws-security.password", PravoRuConstants.PASSWORD);
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.USER, PravoRuConstants.USERNAME);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PravoRuPasswordHandler.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
cxfEndpoint.getOutInterceptors().add(wssOut);