| |
| 使用acegi在业务逻辑层获得Web层的用户ID |
| |
发布者: 发布时间:2007-11-26 |
|
|
|
Acegi安全系统介绍(一)介绍如何在业务接口层获得Web层的用户身份王保政Email:baozhengw@netease.comQQ:29803446MSN:baozhengw999@hotmail.com2006-6-30目 录前 言 3第一章 环境搭建 41.1 环境配置 4第二章 相关的JAVA类 132.1 接口TESTAOPINTERFACE 132.2 接口实现类TESTAOPINTERFACEIMPL 142.3 接口实现类TESTAOPINTERFACE的ADVICE类 142.4 DATASOURCEMETHODDEFINITIONSOURCEEDITOR类 17第三章 测试页面 183.1 登录页面 183.2 登录后进入INDEX.JSP 193.3 调用业务方法的页面 20前 言我在公司产品升级中引入struts+spring+hibernate3的框架时,那时还没有引入Acegi安全系统框架,直到在最近的开发中发现了这样一个问题:Web层可以很容易地得到登录用户的userId,但业务逻辑层的接口如何获得UserId来进行方法调用的安全控制?一开始的接口设计中,有不少方法的第一个参数都是一个String类型的userId变量,但总不能每个方法都带一个userId做为参数吧?那当然不能。那么如何将userId传给业务逻辑层的接口,或者传给业务逻辑接口的前置通知类(MethodBeforeAdvice)?在Advice类获得userId后,就可以根据userId控制方法的执行权限。既然不能使用业务方法中带userId参数的笨拙办法,那么有什么其他的方法可以传递userId呢?我最初考虑由前端传递一个Session,后来又考虑开发一个Listener,但我还没来得及去尝试这些方法的时候,偶尔翻了翻买来的《Spring in Action中文版》中介绍的acegi安全系统,觉得这个安全框架既然能够实现方法级的权限控制,就一定可以解决我现在遇到的问题:我要在业务接口的Advice类中获得登录用户的身份!《Spring in Action中文版》介绍的内容比较基础,没有直接给出一个现成的范例,于是到网上狂找一气,在google上用acegi关键字搜索了10页,找到几篇好文章,最有帮助的应该是网名为“一餐三碗”的先生的一个示例,不过在看他的例子是用acegi0.8.3做的,而我那时手头已经下载了acegi1.0,于是结合acegi1.0下载包和“一餐三碗”老兄的Demo,花了一整天的时间,终于调通了一个基于acegi1.0的例子,这个例子配置了MD5加密,后台的口令验证是根据登录表单的口令进行MD5加密后,与数据库用户表中此用户的加密口令进行比较。我想大家一定很着急先知道我们如何实现在业务方法或Advice类中获得用户身份,所以我先介绍这个例子的具体实现,然后再介绍一下Acegi。第一章 环境搭建1.1 环境配置1、下载acegi:http://nchc.dl.sourceforge.net/sourceforge/acegisecurity/acegi-security-1.0.0-src.ziphttp://prdownloads.sourceforge.net/acegisecurity/acegi-security-1.0.0.zip?download下载后需要将zip文件中的jar包解压出来,放到Web应用可以找到的lib目录下。2、配置MySQL库当然也可以使用其他数据库,这里以MySql库为例,MySql安装好以后需要建几个表,大家可以从这个地址下载“一餐三碗”先生(从名字看应该是男士)提供的例子,里面有数据库表的sql文件: http://www.blogjava.net/Files/youlq/Acegi.zip。3、配置 web.xml〈?xml version="1.0" encoding="GB2312"?〉〈!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"〉〈web-app〉〈display-name〉acegi10〈/display-name〉〈context-param〉〈param-name〉contextConfigLocation〈/param-name〉〈param-value〉/WEB-INF/classes/applicationContext-acegi-security.xml/WEB-INF/classes/applicationContext.xml〈/param-value〉〈/context-param〉〈context-param〉〈param-name〉log4jConfigLocation〈/param-name〉〈param-value〉/WEB-INF/classes/log4j.properties〈/param-value〉〈/context-param〉〈servlet〉〈servlet-name〉SpringContextServlet〈/servlet-name〉〈servlet-class〉org.springframework.web.context.ContextLoaderServlet〈/servlet-class〉〈load-on-startup〉1〈/load-on-startup〉〈/servlet〉〈filter〉〈filter-name〉Acegi Filter Chain Proxy〈/filter-name〉〈filter-class〉org.acegisecurity.util.FilterToBeanProxy〈/filter-class〉〈init-param〉〈param-name〉targetClass〈/param-name〉〈param-value〉org.acegisecurity.util.FilterChainProxy〈/param-value〉〈/init-param〉〈/filter〉〈filter-mapping〉〈filter-name〉Acegi Filter Chain Proxy〈/filter-name〉〈url-pattern〉/*〈/url-pattern〉〈/filter-mapping〉〈!--- Loads the root application context of this web app at startup.- The application context is then available via- WebApplicationContextUtils.getWebApplicationContext(servletContext).--〉〈listener〉〈listener-class〉org.springframework.web.context.ContextLoaderListener〈/listener-class〉〈/listener〉〈listener〉〈listener-class〉org.springframework.web.util.Log4jConfigListener〈/listener-class〉〈/listener〉〈!--The HttpSessionEventPublisher will publishHttpSessionCreatedEvent and HttpSessionDestroyedEventto the WebApplicationContext--〉〈listener〉〈listener-class〉org.acegisecurity.ui.session.HttpSessionEventPublisher〈/listener-class〉〈/listener〉〈/web-app〉4、WEB-INF\classes下的applicationContext.xml文件:〈?xml version="1.0" encoding="UTF-8"?〉〈!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"〉〈beans〉〈bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"〉〈property name="driverClass"〉〈value〉com.mysql.jdbc.Driver〈/value〉〈/property〉〈property name="jdbcUrl"〉〈value〉jdbc:mysql://localhost:3308/acegidb〈/value〉〈/property〉〈property name="user"〉〈value〉root〈/value〉〈/property〉〈property name="password"〉〈value〉mysql〈/value〉〈/property〉〈property name="initialPoolSize"〉〈value〉10〈/value〉〈/property〉〈property name="minPoolSize"〉〈value〉10〈/value〉〈/property〉〈property name="maxPoolSize"〉〈value〉50〈/value〉〈/property〉〈property name="checkoutTimeout"〉〈value〉50000〈/value〉〈/property〉〈property name="maxIdleTime"〉〈value〉1800〈/value〉〈/property〉〈property name="idleConnectionTestPeriod"〉〈value〉3000〈/value〉〈/property〉〈property name="acquireIncrement"〉〈value〉5〈/value〉〈/property〉〈/bean〉〈bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"〉〈property name="dataSource"〉〈ref local="dataSource"/〉〈/property〉〈/bean〉〈bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"〉〈property name="dataSource"〉〈ref bean="dataSource"/〉〈/property〉〈/bean〉〈bean id="businessAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased"〉〈property name="allowIfAllAbstainDecisions"〉〈value〉false〈/value〉〈/property〉〈property name="decisionVoters"〉〈list〉〈ref bean="roleVoter"/〉〈/list〉〈/property〉〈/bean〉〈bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"〉〈property name="customEditors"〉〈map〉〈entry key="org.acegisecurity.intercept.method.MethodDefinitionSource"〉〈bean class="com.mysoft.pmi.security.DataSourceMethodDefinitionSourceEditor"〉〈property name="jdbcTemplate"〉 〈ref bean="jdbcTemplate"/〉 〈/property〉〈/bean〉〈/entry〉〈/map〉〈/property〉〈/bean〉〈bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"〉〈property name="transactionManager"〉〈ref bean="transactionManager"/〉〈/property〉〈property name="transactionAttributeSource"〉〈value〉com.mysoft.pmi.testcase.aop.TestAOPInterfaceImpl.*=PROPAGATION_REQUIRED〈/value〉〈/property〉〈/bean〉〈bean id="contactManagerTarget" class="com.mysoft.pmi.testcase.aop.TestAOPInterfaceImpl" /〉〈bean id="contactManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"〉〈property name="authenticationManager"〉〈ref bean="authenticationManager"/〉〈/property〉〈property name="accessDecisionManager"〉〈ref bean="businessAccessDecisionManager"/〉〈/property〉〈property name="objectDefinitionSource"〉〈value〉select authority,PROTECTED_RES from authorities where AUTH_TYPE='FUNCTION' and authority like 'AUTH_FUNC_ContactManager%'〈/value〉〈/property〉〈/bean〉〈bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean"〉〈property name="proxyInterfaces"〉〈value〉com.mysoft.pmi.testcase.aop.TestAOPInterface〈/value〉〈/property〉〈property name="interceptorNames"〉〈list〉〈idref local="transactionInterceptor"/〉〈idref local="contactManagerSecurity"/〉〈idref local="contactManagerTarget"/〉〈/list〉〈/property〉〈/bean〉〈/beans〉说明:请根据自己机器的配置更改数据库连接地址、端口、数据库名、口令配置参数。com.mysoft.pmi.testcase.aop.TestAOPInterface接口是一个业务逻辑层接口,本例com.mysoft.pmi.testcase.aop.TestAOPInterfaceImpl是此接口的实现类,提供了两个非常简单的接口方法:test和testAAA。另外注意使用“一餐三碗”的数据库导入表结构和数据后,需要修改authorities表PROTECTED_RES的值,因为本例使用的接口为com.mysoft.pmi.testcase.aop.TestAOPInterface,如果此字段使用了不存在的接口和方法,在应用服务器启动时会报错,所以请将此字段的内容改为:com.mysoft.pmi.testcase.aop.TestAOPInterface.test或com.mysoft.pmi.testcase.aop.TestAOPInterface.testAAA,如果大家有兴趣可以在此接口下多加几个方法。5、WEB-INF\classes下的applicationContext-acegi-security.xml文件:〈?xml version="1.0" encoding="UTF-8"?〉〈!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"〉〈beans〉〈bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"〉〈property name="filterInvocationDefinitionSource"〉〈value〉CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISONPATTERN_TYPE_APACHE_ANT/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor〈/value〉〈/property〉〈/bean〉〈bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/〉〈bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"〉〈property name="authenticationManager" ref="authenticationManager"/〉〈property name="authenticationFailureUrl" value="/index_acegi.jsp?login_error=1"/〉〈property name="defaultTargetUrl" value="/testacegi.jsp"/〉〈property name="filterProcessesUrl" value="/j_acegi_security_check"/〉〈/bean〉〈bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/〉〈bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"〉〈property name="authenticationEntryPoint"〉〈bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"〉〈property name="loginFormUrl" value="/acegilogin.jsp"/〉〈property name="forceHttps" value="false"/〉〈/bean〉〈/property〉〈property name="accessDeniedHandler"〉〈bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"〉〈property name="errorPage" value="/accessDenied.jsp"/〉〈/bean〉〈/property〉〈/bean〉〈bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"〉〈property name="authenticationManager" ref="authenticationManager"/〉〈property name="accessDecisionManager"〉〈bean class="org.acegisecurity.vote.AffirmativeBased"〉〈property name="allowIfAllAbstainDecisions" value="false"/〉〈property name="decisionVoters"〉〈list〉〈ref bean="roleVoter"/〉〈bean class="org.acegisecurity.vote.AuthenticatedVoter"/〉〈/list〉〈/property〉〈/bean〉〈/property〉〈property name="objectDefinitionSource"〉〈value〉CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISONPATTERN_TYPE_APACHE_ANT/secure/extreme/**=AUTH_USER/secure/**=IS_AUTHENTICATED_REMEMBERED/**=IS_AUTHENTICATED_ANONYMOUSLY〈/value〉〈/property〉〈/bean〉〈bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"〉〈property name="providers"〉〈list〉〈ref local="daoAuthenticationProvider"/〉〈ref local="anonymousAuthenticationProvider"/〉〈/list〉〈/property〉〈/bean〉〈bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter"〉〈property name="key"〉〈value〉foobar〈/value〉〈/property〉〈property name="userAttribute"〉〈value〉anonymousUser,AUTH_ANONYMOUS〈/value〉〈/property〉〈/bean〉〈bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"〉〈property name="userDetailsService" ref="jdbcDaoImpl"/〉〈property name="userCache"〉〈ref local="userCache"/〉〈/property〉〈!-- if u want encode your password with md5,use property passwordEncoder,otherwise delete row below--〉〈!--〈property name="passwordEncoder" ref="passwordEncoder"/〉--〉〈/bean〉〈bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/〉〈bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/〉〈!-- add --〉〈bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"〉〈property name="dataSource"〉〈ref bean= "dataSource"/〉〈/property〉〈property name="usersByUsernameQuery"〉〈!-- 〈value〉SELECT USERID, USERPASSWORD,IS_ENABLED FROM LTPMIUSER WHERE USERID=?〈/value〉 --〉〈value〉SELECT USERNAME, PASSWORD,ENABLED FROM USERINFO WHERE USERNAME=?〈/value〉〈/property〉〈property name="authoritiesByUsernameQuery"〉〈!--〈value〉SELECT userid,authority FROM ltpmiuser u, authorities a, user_auth uaWHERE u.object_id=ua.user_oidand a.auth_id=ua.auth_idand u.userid = ?〈/value〉--〉〈value〉SELECT username,authority FROM userinfo u, authorities a, user_auth uaWHERE u.user_id=ua.user_idand a.auth_id=ua.auth_idand u.username = ?〈/value〉〈/property〉〈/bean〉〈bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter"〉〈property name="rolePrefix"〉〈value〉AUTH_〈/value〉〈/property〉〈/bean〉〈bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"〉〈property name="key"〉〈value〉foobar〈/value〉〈/property〉〈/bean〉〈bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"〉〈property name="cacheManager"〉 〈ref local="cacheManager"/〉 〈/property〉〈property name="cacheName"〉 〈value〉userCache〈/value〉 〈/property〉〈/bean〉〈bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"〉〈property name="cache"〉〈ref local="userCacheBackend"/〉〈/property〉〈/bean〉〈bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/〉〈/beans〉说明:如果你想使用md5口令验证,请去掉〈!--〈property name="passwordEncoder" ref="passwordEncoder"/〉--〉的注释。6、log4j.properties放在WEB-INF\classes下:log4j.rootLogger=info,CONSOLElog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.Target=System.outlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern= %4p [%t] (%F:%L) - %m%n7、配置业务方法的前置通知(Advice)在业务方法的前置通知类编写获取Web层用户身份的代码,在业务方法的后置通知类编写操作日志的方法调用,在操作日志方法中可通过acegi提供的API来获取当前操作者的Authenticaton。实际上acegi提供了一个非常松散的集成机制,如果你仅需要使用acegi获得Web层的身份,只需要在Advice类中引入acegi的方法,即使我们以后不使用acegi,也使代码的修改非常有限。业务接口:TestAOPInterface。下面是为TestAOPInterface的Advice配置的xml文件aoptest.xml。 文件的类路径为:com.mysoft.pmi.resource。文件内容:〈?xml version="1.0" encoding="UTF-8"?〉〈!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"〉〈beans〉〈bean id="interceptTarget" class="com.mysoft.pmi.testcase.aop.TestAOPInterfaceImpl" singleton="false"/〉〈bean id="welcomeAdvice" class="com.mysoft.pmi.testcase.aop.WelcomeAdvice"/〉〈bean id="aopProxyFactoryBean"class="org.springframework.aop.framework.ProxyFactoryBean"〉〈property name="proxyInterfaces"〉〈list〉〈value〉com.mysoft.pmi.testcase.aop.TestAOPInterface〈/value〉〈/list〉〈/property〉〈property name="interceptorNames"〉〈list〉〈value〉welcomeAdvice〈/value〉〈/list〉〈/property〉〈property name="target"〉〈ref bean="interceptTarget"/〉〈/property〉〈/bean〉〈/beans〉第二章 相关的Java类2.1 接口TestAOPInterface此接口的角色为业务逻辑层接口。package com.mysoft.pmi.testcase.aop;public interface TestAOPInterface{public void test(String arg0,String arg1);public void testAAA(String arg0,String arg1);}2.2 接口实现类TestAOPInterfaceImplpackage com.mysoft.pmi.testcase.aop;public class TestAOPInterfaceImpl implements TestAOPInterface{public void test(String arg0, String arg1) {System.out.println(arg0+"/"+arg1);}public void testAAA(String arg0, String arg1) {System.out.println(arg0+":"+arg1);}}2.3 接口实现类TestAOPInterface的Advice类package com.mysoft.pmi.testcase.aop;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;import org.acegisecurity.context.SecurityContext;import org.acegisecurity.context.SecurityContextHolder;import org.acegisecurity.userdetails.UserDetails;import org.acegisecurity.Authentication;//import org.acegisecurity.vote.RoleVoter;//import org.apache.log4j.Logger;//import org.acegisecurity.providers.ProviderManager;//import org.acegisecurity.vote.AffirmativeBased;//import org.acegisecurity.ui.session.HttpSessionEventPublisher;//import org.acegisecurity.providers.anonymous.AnonymousProcessingFilter;//import org.acegisecurity.providers.dao.DaoAuthenticationProvider;//import org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider;//import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;//import org.acegisecurity.userdetails.jdbc.JdbcDaoImpl;//import org.acegisecurity.userdetails.jdbc.JdbcDaoImpl;//import org.acegisecurity.context.SecurityContextImpl;//import org.acegisecurity.vote.AffirmativeBased;//import org.acegisecurity.userdetails.jdbc.JdbcDaoImpl;//import org.springframework.jdbc.datasource.DataSourceTransactionManager;//import org.springframework.jdbc.core.JdbcTemplate;//import org.springframework.beans.factory.config.CustomEditorConfigurer;//import org.acegisecurity.intercept.method.MethodDefinitionSource;//import org.springframework.transaction.interceptor.TransactionInterceptor;//import org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor;//import org.acegisecurity.providers.*;public class WelcomeAdvice implements MethodBeforeAdvice{public void before(Method method, Object[] args, Object target) throws Throwable{System.out.println("hihihihihi,启动MethodBeforeAdvice ");String userName;SecurityContext ctx = SecurityContextHolder.getContext();if(ctx!=null){System.out.println("ctx is not null");Authentication auth = ctx.getAuthentication();if(auth!=null){System.out.println("auth is not null!");Object principal=auth.getPrincipal();if(principal instanceof UserDetails){//输出用户名System.out.println( "UserName is "+((UserDetails)principal).getUsername());//密码获得System.out.println( "UserPassword is "+((UserDetails)principal).getPassword());}else{System.out.println("pricipal.toString()=="+principal.toString());}}else{System.out.println("auth is null!");}}else{System.out.println("ctx is null");}userName = SecurityContextHolder.getContext().getAuthentication().toString();System.out.println("UserName is:");System.out.println(userName);System.out.println("++++++++++++++++++");//输出被拦截的接口的名称System.out.println(target.getClass().getName());System.out.println(method.getName());for(int i=0;i〈args.length;i++){System.out.println("HI:"+(String)args[i]);//输出传入的字符串参数的值System.out.println( args[i] .getClass().toString());}////Logger song = Logger.getLogger(target.getClass()); //得到目标类的logger//System.out.println("println:"+target.getClass().getName()+" did "+method.getName());}}说明:当接口TestAOPInterface的方法被调用前,WelcomeAdvice类作为此接口的前置通知,其before方法将先于TestAOPInterface的方法(在aoptest.xml中配置了WelcomeAdvice拦截TestAOPInterface的所有方法),在before方法里实现了取得当前会话的Authentication即当前用户的身份。既然取得了用户的登录Id,就可以利用此Id做更细粒度的权限控制及添加系统操作日志(日志需要记录哪个用户调用了此方法),由于acegi的这种授权体系支持到方法级别,可以在Advice中进行更深入的开发-规则引擎的开发。例如在ERP系统中,A库管员和B库管员都可以操作入库单录入功能,但A库管员是原料库库管员,B是成品库库管员,如果成品库库管员录入了原料库物品,则提交入库单操作失败,这样的需求,只提供方法及的授权还不够,可通过开发规则引擎来支持数据级的授权。实现方式可将限制参数于传入的方法实际参数进行比较,如符合规则则继续执行。如果大家想在业务方法里而不是advce类里获得userId,最好是参照上述代码,单独设计一个类封装acegi的调用,以免在业务方法中直接引入acegi的API造成对acegi的过度依赖。2.4 DataSourceMethodDefinitionSourceEditor类package com.mysoft.pmi.security;import org.acegisecurity.intercept.method.MethodDefinitionMap;import org.acegisecurity.ConfigAttributeEditor;import org.acegisecurity.ConfigAttributeDefinition;import java.util.List;import java.util.Iterator;import java.util.Map;import java.beans.PropertyEditorSupport;import org.springframework.jdbc.core.support.JdbcDaoSupport;import org.springframework.jdbc.core.JdbcTemplate;/*** 〈br〉Title:* 〈br〉Description:* 〈br〉Copyright: Copyright.com (c) 2003* 〈br〉Company:* History:* create 2005-11-7 19:02:16** @author youlq* @version 1.0*/public class DataSourceMethodDefinitionSourceEditor extends PropertyEditorSupport{protected JdbcTemplate jdbcTemplate;//~ Methods ================================================================public JdbcTemplate getJdbcTemplate(){return jdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate){this.jdbcTemplate=jdbcTemplate;}public void setAsText(String s) throws IllegalArgumentException{MethodDefinitionMap source=new MethodDefinitionMap();List rs;try{rs=jdbcTemplate.queryForList(s);} catch(Exception e){setValue(source);e.printStackTrace();return;}if((rs==null)||rs.size()==0){// Leave value in property editor null} else{// Now we have properties, process each one individuallyConfigAttributeEditor configAttribEd=new ConfigAttributeEditor();for(Iterator iter=rs.iterator();iter.hasNext();){Map row=(Map)iter.next();String authority=(String)row.get("AUTHORITY");String resource=(String)row.get("PROTECTED_RES");if((null==authority)||(resource==null)){continue;}// Convert value to series of security configuration attributesconfigAttribEd.setAsText(authority);ConfigAttributeDefinition attr=(ConfigAttributeDefinition)configAttribEd .getValue();// Register name and attributesource.addSecureMethod(resource, attr);}}setValue(source);}}第三章 测试页面3.1 登录页面acegilogin.jsp(将此文件放在web应用的根目录下):〈%@ page contentType="text/html;charset=GBK" language="java" %〉〈%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %〉〈%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %〉〈%@ page import="org.acegisecurity.AuthenticationException" %〉〈html〉〈head〉〈title〉Login〈/title〉〈/head〉〈body〉〈h1〉Login〈/h1〉〈%String login_error=request.getParameter("login_error");if(login_error!=null){%〉〈font color="red"〉登录失败。原因: 〈%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %〉〈/font〉〈%}%〉〈form action="j_acegi_security_check" method="POST"〉〈table〉〈tr〉〈td〉User:〈/td〉〈td〉〈input type='text' name='j_username'〉〈/td〉〈/tr〉〈tr〉〈td〉Password:〈/td〉〈td〉〈input type='password' name='j_password'〉〈/td〉〈/tr〉〈tr〉〈td colspan='2'〉〈input name="submit" type="submit"〉〈/td〉〈/tr〉〈tr〉〈td colspan='2'〉〈input name="reset" type="reset"〉〈/td〉〈/tr〉〈/table〉〈/form〉〈/body〉〈/html〉说明:“一餐三碗”提供的数据库表中的root用户口令为root。3.2 登录后进入index.jsp在web应用根目录下建立一个secure目录,此目录下件一个index.jsp文件:〈html〉〈body〉〈h1〉Secure Page〈/h1〉This is a protected page. You can get to me if you've been remembered,or if you've authenticated this session.〈p〉〈a href="../testacegi.jsp"〉Home〈/a〉〈p〉〈a href="../j_acegi_logout"〉Logout〈/a〉〈/body〉〈/html〉3.3 调用业务方法的页面在web应用的根目录下建立一个testacegi.jsp文件:〈%@ page import="org.acegisecurity.context.SecurityContextHolder" %〉〈%@ page import="org.acegisecurity.Authentication" %〉〈%@ page import="org.acegisecurity.ui.AccessDeniedHandlerImpl" %〉〈%@ page import="org.springframework.aop.framework.ProxyFactoryBean"%〉〈%@ page import="org.springframework.context.ApplicationContext"%〉〈%@ page import="org.springframework.context.support.ClassPathXmlApplicationContext"%〉〈%@ page import="com.mysoft.pmi.testcase.aop.TestAOPInterface"%〉〈%System.out.println("_______"+SecurityContextHolder.getContext().getAuthentication().toString());ApplicationContext context1 = new ClassPathXmlApplicationContext("com/mysoft/pmi/resource/aoptest.xml");TestAOPInterface bean1 = (TestAOPInterface)context1.getBean("aopProxyFactoryBean");bean1.test("aa1a","ccc");bean1.testAAA("dd1d","dwdwsd");%〉〈% Authentication auth = SecurityContextHolder.getContext().getAuthentication();if (auth != null) { %〉Authentication object as a String: 〈%= auth.toString() %〉〈BR〉〈BR〉〈% } %〉说明:本文的例子是在Bea Weblogic8.1下测试通过。JSP测试流程:在登录页面输入正确的用户名和口令(如果口令错误,控制台会报bad credentials的错误),登录成功后,浏览器打开了secure/index.jsp页面,点此页面的home连接,此连接调用了testacegi.jsp,此JSP调用了TestAOPInterface的接口方法,可以看到后台显示了当前的userId(见WelcomeAdvice.java)。如果需要将口令进行md5加密,然后与数据库中加密的口令进行比较,可参考applicationContext-acegi-security.xml。
|
| (转载文章请保留出处:北天JAVA技术网(www.java114.com)) |
| |
| 更多精彩文章: |
| 基于Web2.0的AJAX十大安全漏洞以及成因 |
| J2EE程序员应该掌握的Linux系统的知识 |
| 用RMI和CORBA进行分布式Java编程 |
| Sun ONE 白皮书 |
| SOAP--新一轮竞争的三八线?(二) |
| SOAP--新一轮竞争的三八线?(一) |
| |
| 最近评论: |
|
|
| 春暖花开 |
| wow power leveling2
wow power leveling gvf
wow power levelingfcvg
wow power leveling
wow power leveling
wow powerlevelingfcgv
wow powerlevelingwq4
wow powerleveling
wow powerleveling
wow powerleveling
world of warcraft power leveling
world of warcraft power leveling
world of warcraft power leveling
world of warcraft power levelingszr
world of warcraft power leveling
world of warcraft powerleveling
world of warcraft powerlevelinge5t
world of warcraft powerleveling
world of warcraft powerleveling
world of warcraft powerleveling
wow gold
wow gold
wow goldrfy5
wow gold
wow gold
world of warcraft goldre
world of warcraft goldgh
world of warcraft gold
world of warcraft goldfr
world of warcraft gold
AOC Power Levelinggvgv
AGE OF CONAN Power Levelingllwwbb928
m7y6n7xn |
|
|
| 鍥炲 |
|
|
|
| 那个雨天的想法! |
| wow gold,wow power leveling.wow power leveling,wow power leveling,
max(9206) |
|
|
| 如果真的有来生! |
| 四川旅游,九寨沟旅游,稻城亚丁旅游,四姑娘山旅游,海螺沟旅游,西藏旅游,
max(7043) |
|
|
| 如果真的有来生! |
| 四川旅游,九寨沟旅游,稻城亚丁旅游,四姑娘山旅游,海螺沟旅游,西藏旅游,
max(6693) |
|
|
| 左边的风景! |
| wow gold,wow power leveling.wow power leveling,wow power leveling,
max(8422) |
|
|
| 轻轻走过你的窗前! |
| world of warcraft gold,cheap world of warcraft gold,warcraft gold,world of warcraft gold,cheap world of warcraft gold,warcraft gold, max(9500) |
|
|
| 轻轻走过你的窗前! |
| world of warcraft gold,cheap world of warcraft gold,warcraft gold,world of warcraft gold,cheap world of warcraft gold,warcraft gold max(8908) |
|
|
| 不在的哪天! |
| final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,
max(254) |
|
|
| 快乐情人节! |
| wow gold,wow gold,wow gold,wow gold,wow gold,wow gold,wow gold buy wow gold for cheap.
max(3347) |
|
|
| |
| 免责声明:该文章由网友发表,如果对您造成侵权,请联系站长。 |
|