Hi,

I'm developing a SOAP web service *client* hosted in jboss EAP 6.0.1 (CXF
2.4.6).

The service side needs a UserNameToken header but no policy have been
declared in wsdl.

I played with WSS4JOutInterceptor but it is a little bit intrusive.
I didn't found any cxf jax-ws handler for wss4j so I started to try to add
this header with ws-policy.

If I modify the wsdl to add the policy, it works:

   - declare the policy in wsdl:

    <wsp:Policy wsu:Id="UsernameToken" xmlns:wsu="
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd
"
        xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"; xmlns:sp="
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702";>
        <wsp:ExactlyOne>
            <wsp:All>
                <sp:SupportingTokens>
                    <wsp:Policy>
                        <sp:UsernameToken
                            sp:IncludeToken="
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient";
/>
                    </wsp:Policy>
                </sp:SupportingTokens>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>


   - use the policy in the same wsdl:

    <wsdl:binding name="TestServiceSOAP" type="tns:TestService">
        <wsp:PolicyReference xmlns:wsp="
http://schemas.xmlsoap.org/ws/2004/09/policy"; URI="#UsernameToken" />
        <soap:binding style="document" transport="
http://schemas.xmlsoap.org/soap/http"; />
        <wsdl:operation name="sayHello">


   - result is what I expect:

<soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";><soap:Header><wsse:Security
soap:mustUnderstand="1" xmlns:wsse="
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";><wsse:UsernameToken
xmlns:wsu="
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
wsu:Id="UsernameToken-1"><wsse:Username>testUserName</wsse:Username><wsse:Password
Type="
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";>testPassword</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body><ns2:sayHello
xmlns:ns2="http://www.natixis.com/midsav/wsdl/TestService/
"><message>hello</message></ns2:sayHello></soap:Body></soap:Envelope>


But in real life, I cannot modify the wsdl because I'm on client side.
So I tried to dynamically add the the policy as shortly described in
http://cxf.apache.org/using-ws-policy-in-cxf-projects.html

I put the xml ws-policy in a file, load it with neethi and passed the
policy to CXF stack with PolicyConstants.POLICY_OVERRIDE:

    @WebServiceRef
    private TestServiceClient testService;

    public String testWs() {

        TestService port = testService.getTestServiceSOAP();

        // load token policy
        InputStream inputStream =

Thread.currentThread().getContextClassLoader().getResourceAsStream("username-token-ws-policy.xml");
        Policy wsSecuritypolicy = new
PolicyBuilder().getPolicy(inputStream);

        Map<String, Object> requestContext = ((BindingProvider)
port).getRequestContext();
        requestContext.put(SecurityConstants.USERNAME, "testUserName");
        requestContext.put(SecurityConstants.PASSWORD, "testPassword");
        requestContext.put(PolicyConstants.POLICY_OVERRIDE,
wsSecuritypolicy);

        return port.sayHello("hello");

The policy seems to be well charged by the policy interceptor but it
generate a ClassCastException:

Caused by: java.lang.ClassCastException:
org.apache.neethi.builders.PrimitiveAssertion cannot be cast to
org.apache.cxf.ws.security.policy.model.UsernameToken
 at
org.apache.cxf.ws.security.wss4j.UsernameTokenInterceptor.assertUsernameTokens(UsernameTokenInterceptor.java:245)
[cxf-rt-ws-security-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at
org.apache.cxf.ws.security.wss4j.UsernameTokenInterceptor.addUsernameToken(UsernameTokenInterceptor.java:264)
[cxf-rt-ws-security-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at
org.apache.cxf.ws.security.wss4j.UsernameTokenInterceptor.handleMessage(UsernameTokenInterceptor.java:112)
[cxf-rt-ws-security-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at
org.apache.cxf.ws.security.wss4j.UsernameTokenInterceptor.handleMessage(UsernameTokenInterceptor.java:76)
[cxf-rt-ws-security-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
[cxf-api-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
[cxf-rt-core-2.4.9-redhat-2.jar:2.4.9-redhat-2]
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:461)
[cxf-rt-core-2.4.9-redhat-2.jar:2.4.9-redhat-2]


The cast is made on made on UsernameTokenInterceptor:

    private UsernameToken assertUsernameTokens(SoapMessage message,
WSUsernameTokenPrincipal princ) {
        AssertionInfoMap aim = message.get(AssertionInfoMap.class);
        Collection<AssertionInfo> ais =
aim.getAssertionInfo(SP12Constants.USERNAME_TOKEN);
        UsernameToken tok = null;
        for (AssertionInfo ai : ais) {
            *tok = (UsernameToken)ai.getAssertion(); <- cast*

The ai.getAssesrtion() returns a
org.apache.neethi.builders.PrimitiveAssertion instead of
org.apache.cxf.ws.security.policy.model.UsernameToken.

What I have done wrong? I search a lot for samples with
PolicyConstants.POLICY_OVERRIDE but did not find anything.

Best regards,

Christophe

Reply via email to