本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7591042
建立时间:2006年5月29日




[Spring]在SpringSide实现XFire Webservice认证
软件技术

lhwork 发表于 2006/8/8 10:14:43

XFire官方网站提供的基于Webservice认证的例子有问题,在新版本的XFire1.1.2中编译不通过,不过这也是小Case,我后来折腾了一下,为SpringSide提供了一个简单的Webservice认证功能。XFire 跟Spring的天然融合,让我们可以少努力10年就能简单地在Spring中使用Webservice的强大魅力,我从AXIS专向XFire有一些冲 动,也吃了不少亏,但受REST一族的强力吹捧,感觉还是值得尝试的,因此,在公司的系统中也把Axis彻底换了XFire。回到SpringSide,我大概介绍一下如何配置一个真正实用的XFire验证服务。SpringSide中的XFire配置文件放在:SpringSide-bookstore\src\org\springside\bookstore\plugins\webservice\applicationContext-webservice-server.xml我们在里面定义各个Webservice,该文件其实对应于XFire官方的XFire-Servlet.xml看看下面的BookService,这是一个典型的Webservice服务,红色的inHandlers是我挂上去的。它的意思是所有访问BookService的请求都会被先送到authenticationHandler去处理,我们的验证逻辑可以在里面进行。    <!--Web Service 在SpringMVC中的URL 路径映射-->    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">        <property name="mappings">            <value>/BookService=bookWebService</value>        </property>        <property name="inHandlers">            <ref bean="authenticationHandler"/>        </property>    </bean>我们接着看看authenticationHandler的代码:我们在SpringSide中通过header方式向服务器提供验证信息(另外一种更简单的方式是创建一个Login的webservice服务,然后在XFire Session中建立Token信息)。package org.springside.bookstore.plugins.webservice.authentication;import org.apache.log4j.Logger;import org.codehaus.xfire.MessageContext;import org.codehaus.xfire.exchange.InMessage;import org.codehaus.xfire.fault.XFireFault;import org.codehaus.xfire.handler.AbstractHandler;import org.jdom.Element;import org.jdom.Namespace;/** * XFire的回调的Handler,在XFire配置文件中配置 * Server端的认证模块,回调处理模块 *  * ClientAuthHandler跟AuthenticationHandler要一起用,或者都不用 *  * @author  david.turing * @blog  openssl.blogjava.net * */public class AuthenticationHandler extends AbstractHandler {    private static final Logger log = Logger.getLogger(AuthenticationHandler.class);        public void invoke(MessageContext context) throws Exception {                log.info("#AuthenticationHandler is invoked");        InMessage message=context.getInMessage();                final Namespace TOKEN_NS = Namespace.getNamespace("SpringSide","http://service.webservice.plugins.bookstore.springside.org");                  if(message.getHeader()==null)        {            throw new XFireFault("GetRelation Service Should be Authenticated",                    XFireFault.SENDER);        }                Element token = message.getHeader().getChild("AuthenticationToken", TOKEN_NS);        if (token == null)        {            throw new XFireFault("Request must include authentication token.",                                 XFireFault.SENDER);        }        String username = token.getChild("Username", TOKEN_NS).getValue();        String password = token.getChild("Password", TOKEN_NS).getValue();        System.out.println("username="+username);                System.out.println("password="+password);                if(username==null||password==null)            throw new XFireFault("Supplied Username and Password Please",                    XFireFault.SENDER);                /**         * 检查用户名密码是否正确         */        PasswordAuthenticationManager pamanager=new PasswordAuthenticationManager();        if(!pamanager.authenticate(username,password))            throw new XFireFault("Authentication Fail! Check username/password",                    XFireFault.SENDER);             }}注意,XFireFault异常是往客户端抛的,Webservice Client应该学会catch XFireFault.服务器端就是这么简单,看看客户端的TestCasepackage org.springside.bookstore.plugins.webservice.service;import java.lang.reflect.Proxy;import java.net.MalformedURLException;import java.util.List;import org.codehaus.xfire.client.Client;import org.codehaus.xfire.client.XFireProxy;import org.codehaus.xfire.client.XFireProxyFactory;import org.codehaus.xfire.service.Service;import org.codehaus.xfire.service.binding.ObjectServiceFactory;import org.springside.bookstore.commons.domain.Book;import org.springside.bookstore.plugins.webservice.authentication.ClientAuthHandler;import junit.framework.TestCase;public class BookServiceWithAuthenticationTestCase extends TestCase {    protected void setUp() throws Exception {        super.setUp();    }    protected void tearDown() throws Exception {        super.tearDown();    }        public void getBookFromWebservice() throws Exception{              Service serviceModel = new ObjectServiceFactory()                .create(BookService.class);        BookService service = null;                try {            service=(BookService) new XFireProxyFactory().create(                    serviceModel,                    "http://localhost:8080/springside/service/BookService");        } catch (MalformedURLException e) {            e.printStackTrace();        }                Client client = ((XFireProxy) Proxy.getInvocationHandler(service)).getClient();        //挂上ClientAuthHandler,提供认证        client.addOutHandler(new ClientAuthHandler());        List list = service.findBooksByCategory(null);        assertNotNull(list);        for(int i=0;i<list.size();i++)            System.out.println(((Book)list.get(i)).getName());    }}你应该看到上面的client.addOutHandler(new ClientAuthHandler());没错,它跟服务器端的AuthenticationHandler是一对,一起使用的!也就是,每个被送往WebService服务的请求都被ClientAuthHandler处理过了。看看ClientAuthHandler做了些什么:package org.springside.bookstore.plugins.webservice.authentication;import org.apache.log4j.Logger;import org.codehaus.xfire.MessageContext;import org.codehaus.xfire.handler.AbstractHandler;import org.jdom.Element;import org.jdom.Namespace;/** * 客户端端的认证模块,回调处理模块 * 每个需要认证的WebService方法都可以挂这个Handler *  * 仅用于Demo,从解耦和易用性出发, * 没有跟Acegi结合,你可以任意扩展 * 默认用户名/密码是admin/admin *  * ClientAuthHandler跟AuthenticationHandler要一起用,或者都不用 *  * @author  david.turing * * @blog openssl.blogjava.net */    public class ClientAuthHandler extends AbstractHandler {        private static final Logger log = Logger.getLogger(ClientAuthHandler.class);                //客户端自己配置用户名密码或者更安全的KeyStore方式        private String username = "admin";        private String password = "admin";                public ClientAuthHandler() {        }                public ClientAuthHandler(String username,String password) {            this.username = username;            this.password = password;        }                public void setUsername(String username) {            this.username = username;        }                public void setPassword(String password) {            this.password = password;        }                public void invoke(MessageContext context) throws Exception {                                    /*******************************************             * Soap Header方式             * 从Soap Header中获取用户名密码             *******************************************/            final Namespace ns = Namespace.getNamespace("SpringSide","http://service.webservice.plugins.bookstore.springside.org");              Element el = new Element("header",ns);            Element auth = new Element("AuthenticationToken", ns);            Element username_el = new Element("Username",ns);            username_el.addContent(username);            Element password_el = new Element("Password",ns);            password_el.addContent(password);            auth.addContent(username_el);            auth.addContent(password_el);            el.addContent(auth);                        context.getCurrentMessage().setHeader(el);                        log.info("ClientAuthHandler done!");        }    }不就是往header里面注入username,password!在SpringSide中,所有的Spring配置文件都被小白分散到各个Module中去了,Wuyu原先是在Plugin中提供Webservice功能,因此,我仍然在Plugin中创建XFire接口。SpringSide的Spring配置文件放在:SpringSide-bookstore\webapp\WEB-INF\springmvc-servlet.xml该文件定义了Plugin的xml:AuthenticationHandler这个Bean需要先定义在Plugins-servlet.xml中,其它很简单,大家去Try一下就知道了。


阅读全文(1790) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.326 second(s), page refreshed 144765184 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号