Hi Christophe,

The problem, is that you create own Neethi policy builder, that is aware about 
CXF assertions:
> Policy wsSecuritypolicy = new PolicyBuilder().getPolicy(inputStream);

The correct way to do is getting CXF policy builder registered as bus extension:
InputStream is = this.getClass().getResourceAsStream("/ut-policy.xml");
org.apache.cxf.ws.policy.PolicyBuilder builder = 
bus.getExtension(org.apache.cxf.ws.policy.PolicyBuilder.class);
Policy wsSecuritypolicy = builder.getPolicy(is);

Working sample is checked in here: 
https://github.com/ashakirin/cxf.howtos/tree/master/ws-policy.dynamic

By the way I guess the mandatory wsp:Policy element is missing in your 
UsernameToken assertion, this is a valid one:
<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:UsernameToken>
                                </wsp:Policy>
                        </sp:SupportingTokens>
                </wsp:All>
        </wsp:ExactlyOne>
</wsp:Policy>

Regards,
Andrei.

> -----Original Message-----
> From: Christophe Domas [mailto:[email protected]]
> Sent: Freitag, 21. Februar 2014 16:41
> To: [email protected]
> Subject: dynamic ws-policy in message context -> java.lang.ClassCastException:
> org.apache.neethi.builders.PrimitiveAssertion cannot be cast to
> org.apache.cxf.ws.security.policy.model.UsernameToken
> 
> 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><wss
> e: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("userna
> me-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.assertUsernameT
> okens(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.addUsernameTok
> en(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(U
> sernameTokenInterceptor.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(U
> sernameTokenInterceptor.java:76)
> [cxf-rt-ws-security-2.4.9-redhat-2.jar:2.4.9-redhat-2]
>  at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChai
> n.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