I'm having trouble setting the HTTP authorization header to request a web service using Apache CXF. I have my client setup through spring:
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" /> <bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> <bean id="myHTTPAuthInterceptor" class="my.app.MyHTTPAuthInterceptor" autowire="constructor" /> <bean id="webServiceFactory" class="my.app.WebServiceFactory"> <property name="wsdlLocation" value="classpath:/my/app/webservice.wsdl" /> <property name="serviceURL"> <jee:jndi-lookup jndi-name="webservice/url" /> </property> <property name="inInterceptors"> <list> <ref bean="loggingInInterceptor" /> </list> </property> <property name="outInterceptors"> <list> <ref bean="loggingOutInterceptor" /> <ref bean="myHTTPAuthInterceptor" /> </list> </property> </bean> <bean id="myWebService" factory-bean="webServiceFactory" factory-method="getInstance" />
Headers are set via MyHTTPAuthInterceptor as follows:
public MyHTTPAuthInterceptor(ConfigDao configDao) { super(Phase.POST_PROTOCOL); this.configDao = configDao; } @Override public void handleMessage(Message message) throws Fault { Map<String, List<?>> headers = (Map<String, List<?>>) message.get(Message.PROTOCOL_HEADERS); String authString = configDao.getUsername() + ":" + config.getPassword(); headers.put("Authorization", Collections.singletonList("Basic " + new String(Base64.encodeBase64(authString.getBytes())))); }
If the username and both are set to 'test', everything looks fine in the logs:
Headers: {SOAPAction=[""], Accept=[*/*], Authorization=[Basic dGVzdDp0ZXN0]}
However, the server returns HTTP 401: Unauthorized.
Not knowing what was going wrong, I took a completely different approach by changing the factory code of the web service client. I added the basic authorization policy for the client channel as follows:
HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy(); authorizationPolicy.setUserName("test"); authorizationPolicy.setPassword("test"); authorizationPolicy.setAuthorizationType("Basic"); httpConduit.setAuthorization(authorizationPolicy);
Re-checked my setup, same log (different order):
Headers: {SOAPAction=[""], Authorization=[Basic dGVzdDp0ZXN0], Accept=[*/*]}
Now the server response is 200 OK!
A problem that you could solve, but the second approach does not work for me. My application is an environment with several tenants, with different names and passwords. In the second approach, I cannot reuse my client.
How can I make my interceptor work correctly? Am I connecting to the wrong phase? Does the order of the headers mean? If so, how to change it?