`

(转)Acegi配置文档

 
阅读更多

Acegi配置文档
作者:javafish(likunkun)
Email:javafish@sunxin.org
Acegi 是基于Spring的一个开源的安全认证框架,现在的最新版本是1.04。Acegi的特点就是有很多的过滤器:不过我们也用不到这么多的过滤器,只是可 以把它们看作为一个个的模块,在用的时候加上自己用的着的即可,由于认证的流程的方面比较复杂导致它的配置很复杂,如果能摸清它的工作原理还是不太难.下 面用比较顺着人思维的流程过一遍
这里只列出常用的过滤器和拦载器
1. 过滤器:HttpSessionContextIntegrationFilter,authenticationProcessingFilter,BasicProcessingFilter ,RememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter
2. 拦截器:filterSecurityInterceptor(其实它是过滤器,不过把它放在这里更能说明它的功能) ,methodSecurityInterceptor
看 着上面的用红色标出的过滤器是用来认证(表单和HTTP基本认证,当然还有别的不过这两个比较长用)它们是资源访问的入口.其它的过滤器是用来辅助 的:HttpSessionContextIntegrationFilter是用来把认证信息记录到Session中的 RememberMeProcessingFilter是以cookie的形式来保存认证信息的. anonymousProcessingFilter是在匿名的时候(这时候是没有认证信息的)给这个用户分配一个匿名的认证信 息,exceptionTranslationFilter总结一下异常并处理.在实际中选择适合程序的即可.
上面只是资源访问的入口,真正保护资源的是这两个拦截器:filterSecurityInterceptor,拦截URL的类(它是个过滤器)
metohdSecurityInterceptor,拦截类中方法的调用,它们为什么要拦截呢?就是想在访问或调用这些方法之前来判断一下用户是否有访问或调用的权限,有就通过,没有就踢出.
除 此之外,Acegi专门做了两个管理器(实际上就是两个类,为什么会用做这两个管理器,因为认证和授权都有一些的操作,这就需要专门做两个管理器 了):authenticationManager(class= org.acegisecurity.providers.ProviderManager),授权管理器 accessDecisionManager(class=org.acegisecurity.vote.AffirmativeBased)
说白了一个用于认证用户,一个是用于权限的授于的
先 来说认证用户,认证管理器有什么东西呢?只内置了一些提供者:这些提供者呢又是什么呢,他们是提供用户的验证身份信息的,比如从数据库或配置文件里读出用 户名和密码,在用户的cookie里读出身份信息(rememberMeProcessingFilter用到的[前面讲了的,有印象吧]),或在 Session里读出身份验证信息(HttpSessionContextIntegrationFilter起作用的),这里我们只说一下从数据库或配 置文件里读出用户名密码来装配验证信息的,其它的配置类似可以找一下对应api在Spring里配置即 可,daoAuthenticationProvider是数据库的提供者 class=org.acegisecurity.providers.dao.DaoAuthenticationProvider,而它提供的服务呢 又有几种,数据库和配置文件(这是Acegi的两个默认的实现)当然也可以自己实现(实现userDetailsService接口就行)

Java代码 复制代码
  1. <beanid= "authenticationManager" class = "org.acegisecurity.providers.ProviderManager" >
  2. <propertyname= "providers" >
  3. <list>
  4. <reflocal= "daoAuthenticationProvider" />
  5. </list>
  6. </property>
  7. </bean>
  8. <beanid= "daoAuthenticationProvider" class = "org.acegisecurity.providers.dao.DaoAuthenticationProvider" >
  9. <!--<propertyname= "userDetailsService" ><reflocal= "InMemoryDaoImpl" /></property>--><!--这里有两种选择-->
  10. <propertyname= "userDetailsService" ><reflocal= "jdbcDaoImpl" /></property>
  11. </bean>


如果用户名和密码在配置文件里可以用 InMemoryDaoImpl,class=org.acegisecurity.userdetails.memory.InMemoryDaoImpl, 在这个类的userMap里配置即可:javafish=java,ROLE_USER,配置了一个用户名为javafish,密码为java,用户组为 ROLE_USER的用户,不过最常用的还是数据库的JDBC实现(两个二选 一)org.acegisecurity.userdetails.jdbc.JdbcDaoImpl里面需要usersByUsernameQuery 和authoritiesByUsernameQuery还有数据源dataSource(有人问为什么呢,userByUsernameQuery是用 来通过用户名来查密码的,authoritiesByUsernameQuery是用来通过用户名来查权限的,查询数据库肯定的用数据源吧这个里是用的 SpringFrameWork的DataSource)它们查询的sql语句是有讲究的,就是查密码的时候查三个第一个是username,第二个是 password,第三个是是否可用,查权限的时候查两个:username和authorities(具体看例子)

Java代码 复制代码
  1. <beanid= "InMemoryDaoImpl" class = "org.acegisecurity.userdetails.memory.InMemoryDaoImpl" >
  2. <propertyname= "userMap" >
  3. <value>
  4. javafish=java,ROLE_USER
  5. </value>
  6. </property>
  7. </bean>
  8. <beanid= "jdbcDaoImpl" class = "org.acegisecurity.userdetails.jdbc.JdbcDaoImpl" >
  9. <propertyname= "usersByUsernameQuery" >
  10. <value>selectusername,password,enabledfromuserswhereusername=?</value>
  11. </property>
  12. <propertyname= "authoritiesByUsernameQuery" >
  13. <value>selectusername,authorityfromauthoritieswhereusername=?</value>
  14. </property>
  15. <propertyname= "dataSource" >
  16. <reflocal= "dataSource" />
  17. </property>
  18. </bean>
  19. <beanid= "dataSource" class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >
  20. <propertyname= "driverClassName" >
  21. <value>com.mysql.jdbc.Driver</value>
  22. </property>
  23. <propertyname= "url" >
  24. <value>jdbc:mysql: //localhost:3306/test</value>
  25. </property>
  26. <propertyname= "username" >
  27. <value>root</value>
  28. </property>
  29. <propertyname= "password" >
  30. <value>javafish</value>
  31. </property>
  32. </bean>


下面说一下授权,授权管理器又有什么东西呢?accessDecisionManager,Acegi把授权方面弄的比较的形象化,把某个URL或方法是否可以被访问按投票的形式来决定,

Acegi提出来了几种方案:
1. 如果有一个赞成就同意(具体的说就是只要你在那个URL对应的几个用户组中的一个就让你访问)
2. 如果都赞成就同意(具本的说就是那个URL对应的几个用户组里都有你,你才能访问)
3. 如果都不反对就同意(这个在下面讲投票者的时候再说)

Java代码 复制代码
  1. <beanid= "accessDecisionManager" class = "org.acegisecurity.vote.AffirmativeBased" >
  2. <propertyname= "allowIfAllAbstainDecisions" ><!--是否让全部弃权的通过-->
  3. <value> false </value>
  4. </property>
  5. <propertyname= "decisionVoters" ><!--投票者们-->
  6. <refbean= "roleVoter" />
  7. </property>
  8. </bean>


而投票者呢:Acegi自己实现了一个投票者的类RoleVoter:
现在我用第一种方案,RoleVoter只是在URL对应的用户 组里有ROLE_为前缀的才进行投票,否则的话弃权.(我们也可以在配置RoleVoter的时候把ROLE_配置成为别的前缀如JAVA_),分别对 URL对应的每个用户组投票,如果用户在这个用户组里就投赞成,不在投反对(在用户组的前缀是ROLE_的前提下)这样就不难体会第三种方案的用途了吧

Java代码 复制代码
  1. <beanid= "roleVoter" class = "org.acegisecurity.vote.RoleVoter" >
  2. <propertyname= "rolePrefix" >
  3. <value>ROLE_</value><!--可以改成别的-->
  4. </property>
  5. </bean>


这样认证管理器和授权管理器就ok了,别的无论是过滤器还是拦截器都会用到它们两个,因为它们都要验证而这两个就是凭证.
那么那两个访问过滤器呢,先说authenticationProcessingFilter是用于表单登陆的

Java代码 复制代码
  1. <beanid= "authenticationProcessingFilter" class = "org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" >
  2. <propertyname= "authenticationManager" ><refbean= "authenticationManager" /></property>
  3. <propertyname= "authenticationFailureUrl" ><value>/failure.html</value></property><!--登陆失败转向的页面-->
  4. <propertyname= "defaultTargetUrl" ><value>/ok.html</value></property><!--登陆成功转向的页面-->
  5. <propertyname= "filterProcessesUrl" ><value>/check</value></property><!--要验证的地址-->
  6. </bean>


这样的话加上上面配置的认证管理器就已经可以处理登陆了(注意的是它没有用到授权管理器,因为它只是个访问入口还没有权限的授予)
再说一下HTTP基本认证:它比上面的略复杂一点
需要配置一个

Java代码 复制代码
  1. <beanid= "BasicProcessingFilterEntryPoint" class = "org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint" >
  2. <propertyname= "realmName" ><value>javafish</value></property><!--基本认证对话框上显示的字-->
  3. </bean>
  4. 然后
  5. <beanid= "BasicProcessingFilter" class = "org.acegisecurity.ui.basicauth.BasicProcessingFilter" >
  6. <propertyname= "authenticationManager" >
  7. <refbean= "authenticationManager" />
  8. </property>
  9. <propertyname= "authenticationEntryPoint" >
  10. <refbean= "BasicProcessingFilterEntryPoint" />
  11. </property>
  12. </bean>


即可.
不过在HTTP基本认证里需要注意的地方是:好多人配置好了怎么看不到效果啊,一开始我也是很郁闷,看了BasicProcessingFilter的源代码:
String header = httpRequest.getHeader("Authorization");//我们一般进入网页测试的时候这里的header始终是null的

Java代码 复制代码
  1. if (logger.isDebugEnabled()){
  2. logger.debug( "Authorizationheader:" +header);
  3. }
  4. if ((header!= null )&&header.startsWith( "Basic" )){ //从这里可以看到一般的登陆基本认证是不起作用的
  5. .................


只有在服务器上配置哪个目录在访问的时候用HTTP基本认证,它才会起作用(一开始还以为是Acegi的BUG呢)
下面说一下真正对URL资源的保护了filterSecurityInterceptor它的本质是个过滤器,有了前面*管理器的基础了这就很容易了:

Java代码 复制代码
  1. <beanid= "filterSecurityInterceptor" class = "org.acegisecurity.intercept.web.FilterSecurityInterceptor" >
  2. <propertyname= "authenticationManager" >
  3. <reflocal= "authenticationManager" />
  4. </property>
  5. <propertyname= "accessDecisionManager" >
  6. <reflocal= "accessDecisionManager" />
  7. </property>
  8. <propertyname= "objectDefinitionSource" ><!--把URL和可访问的用户组对应起来-->
  9. <value>
  10. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<!--把URL全部转化为小写-->
  11. PATTERN_TYPE_APACHE_ANT<!--以ANT的形式来配置路径-->
  12. /ok.html=ROLE_USER
  13. </value>
  14. </property>
  15. </bean>


光这样配置还是不够的,因为当授权失败的时候会抛出异常的,我们应该配置一个异常过滤器来捕获它,exceptionTranslationFilter它是用来捕获异常的,看一下配置吧:

Java代码 复制代码
  1. <beanid= "exceptionTranslationFilter" class = "org.acegisecurity.ui.ExceptionTranslationFilter" >
  2. <propertyname= "authenticationEntryPoint" ><reflocal= "authenticationProcessingFilterEntryPoint" /></property>
  3. <propertyname= "accessDeniedHandler" >
  4. <bean class = "org.acegisecurity.ui.AccessDeniedHandlerImpl" >
  5. <propertyname= "errorPage" value= "/failure.html" /><!--发生异常转向的网页-->
  6. </bean>
  7. </property>
  8. </bean>
  9. <beanid= "authenticationProcessingFilterEntryPoint" class = "org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint" >
  10. <propertyname= "loginFormUrl" ><value>/Login.html</value></property><!--得到表单的信息-->
  11. <propertyname= "forceHttps" ><value> false </value></property><!--不用https-->
  12. </bean>


这样就OK了
最后说一下对类中方法的保护:
首先写一个类并在spring中配置好:

Java代码 复制代码
  1. package org.li.acegi;
  2. public class TestAcegi
  3. {
  4. public void Role()
  5. {
  6. System.out.println( "javafish" );
  7. }
  8. }
  9. <beanid= "testAcegi" class = "org.li.acegi.TestAcegi" />


然看写个servlet访问一下它

Java代码 复制代码
  1. package org.li.servlet;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import org.li.acegi.TestAcegi;
  9. import org.springframework.context.ApplicationContext;
  10. import org.springframework.web.context.support.WebApplicationContextUtils;
  11. public class TestServlet extends HttpServlet
  12. {
  13. private static final long serialVersionUID=-5610016980827214773L;
  14. public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)
  15. throws ServletException,IOException
  16. {
  17. response.setContentType( "text/html;charset=GBK" );
  18. PrintWriterout=response.getWriter();
  19. ApplicationContextctx=
  20. WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
  21. TestAcegitest=(TestAcegi)ctx.getBean( "testAcegi" );
  22. test.Role(); //访问TestAcegi类的Role方法
  23. out.println( "调用成功" );
  24. }
  25. public void doPost(HttpServletRequestrequest,HttpServletResponseresponse)
  26. throws ServletException,IOException
  27. {
  28. doGet(request,response);
  29. }
  30. }


准备工作做好了,开始配置Acegi
先在Spring里给Acegi做个代理:

Java代码 复制代码
  1. <beanid= "autoProxyCreator" class = "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
  2. <propertyname= "beanNames" >
  3. <list>
  4. <value>testAcegi</value><!--要代理的Bean的id-->
  5. </list>
  6. </property>
  7. <propertyname= "interceptorNames" >
  8. <list>
  9. <value>methodSecurityInterceptor</value><!--代理为...-->
  10. </list>
  11. </property>
  12. </bean>


里面的methodSecurityInterceptor呢配置为:

Java代码 复制代码
  1. <beanid= "methodSecurityInterceptor" class = "org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor" >
  2. <propertyname= "authenticationManager" >
  3. <refbean= "authenticationManager" />
  4. </property>
  5. <propertyname= "accessDecisionManager" >
  6. <refbean= "accessDecisionManager" />
  7. </property>
  8. <propertyname= "objectDefinitionSource" ><!--对代理的类的方法开始配置权限-->
  9. <value>org.li.acegi.TestAcegi.Role=ROLE_USER</value>
  10. </property>
  11. </bean>


这样当直接访问http://localhost:8080/AcegiWeb/servlet/TestServlet的时候会发现不可访问,控件台也不输出”javafish”,当输入正确的用户名和密码之后便可以访问.
这样它就对类的方法调用起了保护的作用,这一点可以把Acegi应用到DWR上效果是很理想的.
对于Acegi有很多的过滤器不用全写在web.xml里,acegi提供了一个特殊的过滤器我们可以写成这样,在Web.xml里:

Java代码 复制代码
  1. <filter>
  2. <filter-name>Acegi</filter-name>
  3. <filter- class >org.acegisecurity.util.FilterToBeanProxy</filter- class >
  4. <init-param>
  5. <param-name>targetClass</param-name>
  6. <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>Acegi</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>
  13. <context-param>
  14. <param-name>contextConfigLocation</param-name>
  15. <param-value>
  16. /WEB-INF/applicationContext.xml
  17. </param-value>
  18. </context-param>
  19. <listener>
  20. <listener- class >org.springframework.web.context.ContextLoaderListener</listener- class >
  21. </listener>
  22. <listener>
  23. <listener- class >org.springframework.web.util.Log4jConfigListener</listener- class >
  24. </listener>
  25. <listener>
  26. <listener- class >org.acegisecurity.ui.session.HttpSessionEventPublisher</listener- class >
  27. </listener>
  28. <servlet>
  29. <servlet-name>TestServlet</servlet-name>
  30. <servlet- class >org.li.servlet.TestServlet</servlet- class >
  31. </servlet>
  32. <servlet-mapping>
  33. <servlet-name>TestServlet</servlet-name>
  34. <url-pattern>/servlet/TestServlet</url-pattern>
  35. </servlet-mapping>


在Spring的配置文件里:

Java代码 复制代码
  1. <beanid= "chainProxy" class = "org.acegisecurity.util.FilterChainProxy" >
  2. <propertyname= "filterInvocationDefinitionSource" >
  3. <value>
  4. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  5. PATTERN_TYPE_APACHE_ANT
  6. /**=HttpSessionContextIntegrationFilter,authenticationProcessingFilter,BasicProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
  7. </value>
  8. </property>
  9. </bean>
分享到:
评论

相关推荐

    权限Acegi的使用

    Acegi是大明鼎鼎都开源权限控制框架,权限Acegi的使用文档,帮助你在应用系统中配置权限.

    acegi_help.zip_Help!_acegi

    著名的acegi的框假说明文档,对配置acegi系统很有帮助

    acegi 入门培训教程

    本文档适合对acegi没多少基础的朋友学习,里面详细的讲述了acegi的基本配置信息。对于acegi不了解的朋友很值得一看,

    Acegi开发项目教程.pdf

    相信不少朋友们对于学习Acegi的过程是比较痛苦的,而且可能最初一个例子都没能真正运行起来。即使能运行起来,对 ...相信你认真看完本文档后肯定会对acegi有很大的了解对使用acegi应该不会有太大的问题

    Acegi解决权限问题

    Acegi解决权限问题,内含全部代码,包括文档及配置文件的说明,可以运行起来。

    spring security 的一些资料----下载不扣分,回帖加1分,童叟无欺,欢迎下载

    Spring Security中可以使用Acegi-1.x时代的普通配置方式,也可以使用从2.0时代才出现的命名空间配置方式,实际上这两者实现的功能是完全一致的,只是新的命名空间配置方式可以把原来需要几百行的配置压缩成短短的几...

    Spring Security-3.0.1中文官方文档(翻译版)

    16. acegi 到spring security 的转换方式 16.1. Spring Security 是什么 16.2. 目标 16.3. 步骤 16.4. 总结 V. 高级话题 17. 领域对象安全(ACLs) 17.1. 概述 17.2. 关键概念 17.3. 开始 18. 预...

    jasypt API Docs 1.9 (CHM格式)

    Jasypt 1.4的新特征包括:加密属性文件(encryptable properties files)、Spring Framework集成、加密Hibernate数据源配置、新的命令行工具、URL加密的Apache wicket集成以及升级文档。 根据Jasypt文档,该技术可...

    DWR中文文档.pdf

    39 4.6.2 HibernateBeanConverter 39 4.6.3 Session管理 39 4.7 DWR与WebWork 40 4.7.1 配置dwr.xml 40 4.7.2 在JSP中导入脚本 40 4.7.3 高级 41 4.8 DWR与Acegi 42 4.8.1 问题提出...

    jasypt-1.9.3-dist.zip

    根据Jasypt官方文档,Jasypt可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信、创建完整检查数据的sums. 其他性能包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二...

    jasypt-1.9.3.jar

    &gt;根据Jasypt官方文档,Jasypt可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信、创建完整检查数据的sums. 其他性能包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二...

    spring in action英文版

     9.4.2 产生PDF文档  9.4.3 产生其他非HTML文件  9.5 小结  第10章 使用其他Web框架  10.1 使用Jakarta Struts  10.1.1 注册Spring插件  10.1.2 实现知晓Spring的Struts action  10.1.3 委托...

    Roller4.0的另外一套cas简单解决方案

    我自己下了一套acegi配置了一下.成功了.同样的方法放到roller里面就挂掉了..(无语中….)所以只好另找方法. 注:下文中所说的如图均在该文所附带的下载包中有相应的word说明. 1.搭建roller的myeclipse环境. 首先搭建...

    spring security 2.0 安全框架实例(改进版)

    你可以在spring参考文档得到更多信息。 命名空间元素可以简单的配置单个bean,或使用更强大的,定义一个备用配置语法,这可以更加紧密的匹配问题域,隐藏用户背后的复杂性。 简单元素可能隐藏事实,多种bean和处理...

    java文集

    映射标记 Java的“静态库链接” 姚博文 集成ACEGI 进行权限控制 SWT可交互式Browser控件 JDK配置(注意) RIA简介(第一部分) 在 Eclipse 中嵌入 NASA World Wind Java SDK, 用3DES加密解密 ...

    JAVA上百实例源码以及开源项目

    百度云盘分享 简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 ...

    java开源包1

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包11

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

Global site tag (gtag.js) - Google Analytics