我在使用 Apache CXF 为 Web 服务请求设置 HTTP 授权标头时遇到了一些问题。我在春天有我的客户设置:
<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" />
标头通过 MyHTTPAuthInterceptor 设置,如下所示:
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()))));
}
使用用户名并将两者都设置为“测试”,日志中的一切似乎都正常:
Headers: {SOAPAction=[""], Accept=[*/*], Authorization=[Basic dGVzdDp0ZXN0]}
但是,服务器返回 HTTP 401:未经授权。
不知道出了什么问题,我通过更改我的 Web 服务客户端工厂代码采取了另一种方法。我向客户端的管道添加了一个基本授权策略,如下所示:
HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy();
authorizationPolicy.setUserName("test");
authorizationPolicy.setPassword("test");
authorizationPolicy.setAuthorizationType("Basic");
httpConduit.setAuthorization(authorizationPolicy);
再次测试我的设置,相同的日志(尽管顺序不同):
Headers: {SOAPAction=[""], Authorization=[Basic dGVzdDp0ZXN0], Accept=[*/*]}
现在服务器的响应是 200 OK!
您可能会认为问题已解决,但第二种方法对我来说并不适用。我的应用程序是一个多租户环境,都有不同的用户名和密码。使用第二种方法,我无法重用我的客户。
如何让我的拦截器正常工作?我是否插入了错误的阶段?标题的顺序重要吗?如果是这样,我该如何改变它?