java Apache CXF - 凭证不是从 WSS4JOutInterceptor 发送的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5906154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:22:33  来源:igfitidea点击:

Apache CXF - credentials not being sent from WSS4JOutInterceptor?

javaweb-servicescxfws-security

提问by bwsmith

I am trying to connect to a web service using WS-Security UsernameToken spec 1.0, using apache cxf 2.4.0.

我正在尝试使用 WS-Security UsernameToken 规范 1.0,使用 apache cxf 2.4.0 连接到 Web 服务。

I've copied the code below from the CXF docs, but am getting: org.apache.cxf.ws.policy.PolicyException: No username available

我已经从 CXF 文档中复制了下面的代码,但我得到了:org.apache.cxf.ws.policy.PolicyException: No username available

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

I've also implemented a ClientPasswordHandler class, again from the docs, but it seems like the username is never sent (according to the error). Here is the password handler:

我还实现了一个 ClientPasswordHandler 类,同样来自文档,但似乎从未发送过用户名(根据错误)。这是密码处理程序:

public class ClientPasswordHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    pc.setPassword("Password");     
    }
}

Is there any way to see if the WSS4Jinterceptor is being applied, and the UsernameToken is sent?

有什么办法可以查看是否正在应用WSS4Jinterceptor,并发送UsernameToken?

回答by Daniel Kulp

Are you getting the PolicyException on the client side? If so, that likely means the WSDL you are using has a WS-SecucurityPolicy fragment in it that describes the UsernameToken policy that it wants and is expecting. If that's the case, then you shouldn't configure the WSS4JOutInterceptor at all. The WS-Policy runtime will handle it and you just need to provide some properties that it may need.

您是否在客户端收到 PolicyException?如果是这样,这可能意味着您正在使用的 WSDL 中有一个 WS-SecucurityPolicy 片段,它描述了它想要和期待的 UsernameToken 策略。如果是这种情况,那么您根本不应该配置 WSS4JOutInterceptor。WS-Policy 运行时将处理它,您只需要提供它可能需要的一些属性。

The docs for the SecurityPolicy stuff are at: http://cxf.apache.org/docs/ws-securitypolicy.html

SecurityPolicy 的文档位于:http: //cxf.apache.org/docs/ws-securitypolicy.html

You likely just need to use:

您可能只需要使用:


Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "USERNAME");
ctx.put("ws-security.password", "Password");

回答by Alex Punnen

On using the answer from Daniel, I was getting the following exception

在使用 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)

I used the below and it started working

我使用了下面的,它开始工作

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

回答by Kirill Ch

Thanks to Daniel the full working configuration for me is the following:

感谢 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);