使用 cxf (JaxWsProxyFactoryBean) 测试摘要认证的 webservice 客户端
Posted
技术标签:
【中文标题】使用 cxf (JaxWsProxyFactoryBean) 测试摘要认证的 webservice 客户端【英文标题】:webservice client using cxf (JaxWsProxyFactoryBean) to test digest authentication 【发布时间】:2013-09-22 16:26:46 【问题描述】:如何使用 cxf (JaxWsProxyFactoryBean) 将摘要身份验证类型设置为 Web 服务客户端?到目前为止,当我在工厂对象中设置用户名密码时,我的客户端默认假定基本身份验证类型。并且请求消息头中包含“Authentication [Basic: ......]”。我想为摘要身份验证设置一个 cxf 客户端。你能帮忙吗? (WS 使用 CXF 和 Spring 3 在 Java 中实现)
我已经为 Digest auth 配置了 Spring Security,如下所示...
<security:http entry-point-ref="digestEntryPoint">
<security:intercept-url pattern="/**" requires-channel="any" access="ROLE_WS_USER" />
<security:custom-filter ref="digestAuthenticationFilter" position="BASIC_AUTH_FILTER"/>
</security:http>
<bean id="digestAuthenticationFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<property name="userDetailsService" ref="userService"/>
<property name="authenticationEntryPoint" ref="digestEntryPoint"/>
</bean>
<bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<property name="realmName" value="My Webservice"/>
<property name="key" value="acegi"/>
<property name="nonceValiditySeconds" value="10" />
</bean>
<bean id="userService" class="com.wallstreetsystems.ws.config.SpringSecurityUserDetailsService">
</bean>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService"/>
</security:authentication-manager>
而java客户端是……
public static void main(String args[]) throws Exception
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(OrderNUmber.class);
factory.setAddress(ht..://localh..:9000/ws/OderNumberService);
factory.setUsername("bob");
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER,"bob");
outProps.put(WSHandlerConstants.PASSWORD_TYPE,WSConstants.PW_DIGEST);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
factory.getOutInterceptors().add(wssOut);
String orderNo = orderNumber.getNextOrderNumber();
System.out.println(orderNo);
我正在嵌入式 Jetty 上部署和运行测试。错误日志如下......
ID: 1
Address: ht..://localh...:9000/ws/OrderNumberService
Encoding: UTF-8
Content-Type: text/xml
Headers: Accept=[*/*], SOAPAction=["getNextOrderNumber"]
Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security xmlns:wsse="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><wsse:UsernameToken wsu:Id="UsernameToken-1"><wsse:Username>bob</wsse:Username><wsse:Password Type="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobspassword</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body/></soap:Envelope>
--------------------------------------
2013-09-23 14:07:36,887 [294071597@qtp-1153274506-2] INFO org.apache.cxf.services.OrderNumberService.OrderNumberPort.OrderNumber - Inbound Message
----------------------------
ID: 2
Address: ht..://localhost:9000/ws/OrderNumberService
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[616], content-type=[text/xml; charset=UTF-8], Host=[localhost:9000], Pragma=[no-cache], SOAPAction=["getNextOrderNumber"], User-Agent=[Apache CXF 2.6.2]
Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security xmlns:wsse="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><wsse:UsernameToken wsu:Id="UsernameToken-1"><wsse:Username>bob</wsse:Username><wsse:Password Type="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobspassword</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body/></soap:Envelope>
--------------------------------------
2013-09-23 14:07:36,911 [294071597@qtp-1153274506-2] WARN org.apache.cxf.phase.PhaseInterceptorChain - Interceptor for ht..://www.xyz.comOrderNumberService#ht..://www.xyz.comgetNextOrderNumber has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: MustUnderstand headers: [ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsdSecurity] are not understood.
at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.checkUltimateReceiverHeaders(MustUnderstandInterceptor.java:150)
at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.handleMessage(MustUnderstandInterceptor.java:96)
at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.handleMessage(MustUnderstandInterceptor.java:49)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:193)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:221)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:141)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:197)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1148)
at com.myproject.ws.config.WSSWebSecurityFilterChain.doFilter(WSSWebSecurityFilterChain.java:64)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:880)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:747)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
2013-09-23 14:07:36,940 [main] INFO org.apache.cxf.services.OrderNumberService.OrderNumberPort.OrderNumber - Inbound Message
----------------------------
ID: 1
Response-Code: 500
Encoding: UTF-8
Content-Type: text/xml; charset=utf-8
Headers: Content-Length=[340], content-type=[text/xml; charset=utf-8], Server=[Jetty(6.1.15)]
Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>MustUnderstand headers: [ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsdSecurity] are not understood.</faultstring></soap:Fault></soap:Body></soap:Envelope>
--------------------------------------
2013-09-23 14:07:37,021 [main] INFO /ws - Closing Spring root WebApplicationContext
问题:正如您在请求消息头中看到的那样,没有“Authentication [Digest:....”,并且请求被视为没有身份验证的普通请求。但是当请求到达被配置为拦截摘要请求的服务提供者时会抛出错误。
我想在客户端将身份验证类型设置为摘要,以便将请求视为摘要请求。
【问题讨论】:
【参考方案1】:这就是我修复它的方法:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress("localhost:9000/OrderNumberService");
OrderNumberService orderNumberClient = factory.create(OrderNumberService.class);
Client client = ClientProxy.getClient(orderNumberClient);
HTTPConduit http = (HTTPConduit) client.getConduit();
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setAuthorizationType("Digest");
authPolicy.setUserName("foo");
authPolicy.setPassword("bar");
http.setAuthorization(authPolicy);
【讨论】:
以上是关于使用 cxf (JaxWsProxyFactoryBean) 测试摘要认证的 webservice 客户端的主要内容,如果未能解决你的问题,请参考以下文章
CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)
WebService -- Java 实现之 CXF ( 使用:Spring+CXF+Tomcat发布webService)
黑马Android(15)cxf 介绍 以及ant 工具的使用/cxf总结