WebService开发笔记 3 -- 增强访问 WebService 的安全性
在WebService开发笔记 1中我们创建了一个WebService简单实例,下面我们通过一个简单的用户口令验证机制来加强一下WebService的安全性:
1.修改WebService 服务端 spring 配置文件 ws-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jaxws="http://cxf.apache.org/jaxws"xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"default-autowire="byName" default-lazy-init="true"><jaxws:endpoint id="webServiceSample"address="/WebServiceSample" implementor="cn.org.coral.biz.examples.webservice.WebServiceSampleImpl"><jaxws:inInterceptors><bean /><bean value="UsernameToken" /><entry key="passwordType" value="PasswordText" /><entry key="passwordCallbackClass" value="cn.org.coral.biz.examples.webservice.handler.WsAuthHandler" /></map></constructor-arg></bean></jaxws:inInterceptors></jaxws:endpoint></beans>
2.服务端添加passwordCallbackClass回调类,该类进行用户口令验证:
package cn.org.coral.biz.examples.webservice.handler;import java.io.IOException;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;import javax.security.auth.callback.UnsupportedCallbackException;import org.apache.ws.security.WSPasswordCallback;public class WsAuthHandler implements CallbackHandler{public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; if (pc.getIdentifer().equals("ws-client")){ if (!pc.getPassword().equals("admin")) { throw new SecurityException("wrong password"); } }else{ throw new SecurityException("wrong username"); }}}3.客户端修改spring 配置文件 wsclient-context.xml 如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jaxws="http://cxf.apache.org/jaxws"xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"default-autowire="byName" default-lazy-init="true"><!-- ws clinet --><bean id="webServiceSampleClient" factory-method="create" /><bean id="webServiceSampleClientFactory"/><property name="address"value="http://88.148.29.54:8080/aio/services/WebServiceSample" /><property name="outInterceptors"><list><bean/><ref bean="wss4jOutConfiguration" /></list></property></bean><bean id="wss4jOutConfiguration"value="UsernameToken" /><entry key="user" value="ws-client" /><entry key="passwordType" value="PasswordText" /><entry><key><value>passwordCallbackRef</value></key><ref bean="passwordCallback" /></entry></map></property></bean><bean id="passwordCallback"name="code">package cn.org.coral.biz.examples.webservice.handler;import java.io.IOException;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;import javax.security.auth.callback.UnsupportedCallbackException;import org.apache.ws.security.WSPasswordCallback;public class WsClinetAuthHandler implements CallbackHandler{ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; int usage = pc.getUsage(); System.out.println("identifier: " + pc.getIdentifer()); System.out.println("usage: " + pc.getUsage()); if (usage == WSPasswordCallback.USERNAME_TOKEN) { // username token pwd... pc.setPassword("admin"); } else if (usage == WSPasswordCallback.SIGNATURE) { // set the password for client's keystore.keyPassword pc.setPassword("keyPassword"); } } } }5.junit单元测试程序:
package cn.org.coral.biz.examples.webservice;import org.springframework.test.AbstractDependencyInjectionSpringContextTests;import org.springframework.util.Assert;public class TestWebService extends AbstractDependencyInjectionSpringContextTests {WebServiceSample webServiceSampleClient;@Overrideprotected String[] getConfigLocations() {setAutowireMode(AUTOWIRE_BY_NAME);return new String[] { "classpath:/cn/org/coral/biz/examples/webservice/wsclient-context.xml" };}/** * @param webServiceSampleClient the webServiceSampleClient to set */public void setWebServiceSampleClient(WebServiceSample webServiceSampleClient) {this.webServiceSampleClient = webServiceSampleClient;}public void testSay(){String result = webServiceSampleClient.say(" world");Assert.hasText(result);}} 1 楼 sskhnje 2008-08-19 你好, 我也看了CXF的文档, 怎么我除了配helloworld外什么都没学到, 请问你是怎么学的?期望你的指教, 谢谢啊! 2 楼 sskhnje 2008-08-20 你好, 我的是cxf2.1.1 出现了以下异常, 谢谢啊!
org.apache.cxf.binding.soap.SoapFault: Problems creating SAAJ object model
at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:117)
at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:63)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:221)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:449)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1996)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1832)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:591)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:221)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:296)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:242)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:178)
at $Proxy43.sayHi(Unknown Source)
at a.Client.main(Client.java:38)
Caused by: javax.xml.soap.SOAPException: Failed to create MessageFactory: org.apache.axis.soap.MessageFactoryImpl
at javax.xml.soap.MessageFactory.newInstance(MessageFactory.java:55)
at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:77)
... 15 more 3 楼 zhunzhunzhun-sky 2008-09-02 是啊,我想知道你是怎么学的~~~ 4 楼 zhengguang_xia 2009-01-16 如果能加点注释,解释下就好了 5 楼 冰火人 2011-08-31 请问楼主这个是你自己的还是转的别人的,你自己测试了没有!
服务端 passwordCallbackClass中:pc.getPassword()这里有值???
…………
6 楼 chxiaowu 2011-11-25 No bean named 'cxf' is defined
?????????? 7 楼 chxiaowu 2011-11-25 严重: StandardWrapper.Throwable
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cxf' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:971)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:246)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:884)
at org.apache.cxf.transport.servlet.CXFServlet.loadBus(CXFServlet.java:60)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.init(CXFNonSpringServlet.java:56)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1228)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1147)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:836)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1824)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
2011-11-25 16:09:45 org.apache.catalina.core.StandardWrapperValve invoke 8 楼 chxiaowu 2011-11-25 从头到尾没发现 那里有 cxf bean配置啊。。。。