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