浅谈Acegi配置

news/2024/7/16 6:29:42 标签: Acegi, 配置管理, Bean, Servlet, Spring
<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/46860.html" frameborder="0" width="468" scrolling="no" height="60"></iframe>
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接口就行)
代码
  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>
render_code();
如果用户名和密码在配置文件里可以用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(具体看例子)
代码
  1. beanid="InMemoryDaoImpl"class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
  2. propertyname="userMap">
  3. value>
  4. javajavafish=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.Drivervalue>
  22. property>
  23. propertyname="url">
  24. value>jdbc:mysql://localhost:3306/testvalue>
  25. property>
  26. propertyname="username">
  27. value>rootvalue>
  28. property>
  29. propertyname="password">
  30. value>javafishvalue>
  31. property>
  32. bean>
render_code();
下面说一下授权,授权管理器又有什么东西呢?accessDecisionManager,Acegi把授权方面弄的比较的形象化,把某个URL或方法是否可以被访问按投票的形式来决定,

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

代码
  1. beanid="accessDecisionManager"class="org.acegisecurity.vote.AffirmativeBased">
  2. propertyname="allowIfAllAbstainDecisions"><!--是否让全部弃权的通过-->
  3. value>falsevalue>
  4. property>
  5. propertyname="decisionVoters"><!--投票者们-->
  6. refbean="roleVoter"/>
  7. property>
  8. bean>
render_code();
而投票者呢:Acegi自己实现了一个投票者的类RoleVoter:
现在我用第一种方案,RoleVoter只是在URL对应的用户组里有ROLE_为前缀的才进行投票,否则的话弃权.(我们也可以在配置RoleVoter的时候把ROLE_配置成为别的前缀如JAVA_),分别对URL对应的每个用户组投票,如果用户在这个用户组里就投赞成,不在投反对(在用户组的前缀是ROLE_的前提下)这样就不难体会第三种方案的用途了吧
代码
  1. beanid="roleVoter"class="org.acegisecurity.vote.RoleVoter">
  2. propertyname="rolePrefix">
  3. value>ROLE_value><!--可以改成别的-->
  4. property>
  5. bean>
render_code();
这样认证管理器和授权管理器就ok了,别的无论是过滤器还是拦截器都会用到它们两个,因为它们都要验证而这两个就是凭证.
那么那两个访问过滤器呢,先说authenticationProcessingFilter是用于表单登陆的
代码
  1. beanid="authenticationProcessingFilter"class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  2. propertyname="authenticationManager">refbean="authenticationManager"/>property>
  3. propertyname="authenticationFailureUrl">value>/failure.htmlvalue>property><!--登陆失败转向的页面-->
  4. propertyname="defaultTargetUrl">value>/ok.htmlvalue>property><!--登陆成功转向的页面-->
  5. propertyname="filterProcessesUrl">value>/checkvalue>property><!--要验证的地址-->
  6. bean>
render_code();
这样的话加上上面配置的认证管理器就已经可以处理登陆了(注意的是它没有用到授权管理器,因为它只是个访问入口还没有权限的授予)
再说一下HTTP基本认证:它比上面的略复杂一点
需要配置一个
代码
  1. beanid="BasicProcessingFilterEntryPoint"class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
  2. propertyname="realmName">value>javafishvalue>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>
render_code();
即可.
不过在HTTP基本认证里需要注意的地方是:好多人配置好了怎么看不到效果啊,一开始我也是很郁闷,看了BasicProcessingFilter的源代码:
String header = httpRequest.getHeader("Authorization");//我们一般进入网页测试的时候这里的header始终是null的
代码
  1. if(logger.isDebugEnabled()){
  2. logger.debug("Authorizationheader:"+header);
  3. }
  4. if((header!=null)&&header.startsWith("Basic")){//从这里可以看到一般的登陆基本认证是不起作用的
  5. .................
render_code();
只有在服务器上配置哪个目录在访问的时候用HTTP基本认证,它才会起作用(一开始还以为是Acegi的BUG呢)
下面说一下真正对URL资源的保护了filterSecurityInterceptor它的本质是个过滤器,有了前面*管理器的基础了这就很容易了:
代码
  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>
render_code();
光这样配置还是不够的,因为当授权失败的时候会抛出异常的,我们应该配置一个异常过滤器来捕获它,exceptionTranslationFilter它是用来捕获异常的,看一下配置吧:
代码
  1. beanid="exceptionTranslationFilter"class="org.acegisecurity.ui.ExceptionTranslationFilter">
  2. propertyname="authenticationEntryPoint">reflocal="authenticationProcessingFilterEntryPoint"/>property>
  3. propertyname="accessDeniedHandler">
  4. beanclass="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.htmlvalue>property><!--得到表单的信息-->
  11. propertyname="forceHttps">value>falsevalue>property><!--不用https-->
  12. bean>
render_code();
这样就OK了
最后说一下对类中方法的保护:
首先写一个类并在spring中配置好:
代码
  1. packageorg.li.acegi;
  2. publicclassTestAcegi
  3. {
  4. publicvoidRole()
  5. {
  6. System.out.println("javafish");
  7. }
  8. }
  9. <bean><span class="string">"testAcegi"</span><span></span><span class="keyword">class</span><span>=</span><span class="string">"org.li.acegi.TestAcegi"</span><span>/&gt; </span></bean>
render_code();
然看写个servlet访问一下它
代码
  1. packageorg.li.servlet;
  2. importjava.io.IOException;
  3. importjava.io.PrintWriter;
  4. importjavax.servlet.ServletException;
  5. importjavax.servlet.http.HttpServlet;
  6. importjavax.servlet.http.HttpServletRequest;
  7. importjavax.servlet.http.HttpServletResponse;
  8. importorg.li.acegi.TestAcegi;
  9. importorg.springframework.context.ApplicationContext;
  10. importorg.springframework.web.context.support.WebApplicationContextUtils;
  11. publicclassTestServletextendsHttpServlet
  12. {
  13. privatestaticfinallongserialVersionUID=-5610016980827214773L;
  14. publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
  15. throwsServletException,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. publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
  26. throwsServletException,IOException
  27. {
  28. doGet(request,response);
  29. }
  30. }
render_code();
准备工作做好了,开始配置Acegi
先在Spring里给Acegi做个代理:
代码
  1. beanid="autoProxyCreator"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  2. propertyname="beanNames">
  3. list>
  4. value>testAcegivalue><!--要代理的Bean的id-->
  5. list>
  6. property>
  7. propertyname="interceptorNames">
  8. list>
  9. value>methodSecurityInterceptorvalue><!--代理为...-->
  10. list>
  11. property>
  12. bean>
render_code();
里面的methodSecurityInterceptor呢配置为:
代码
  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_USERvalue>
  10. property>
  11. bean>
render_code();
这样当直接访问http://localhost:8080/AcegiWeb/servlet/TestServlet的时候会发现不可访问,控件台也不输出”javafish”,当输入正确的用户名和密码之后便可以访问.
这样它就对类的方法调用起了保护的作用,这一点可以把Acegi应用到DWR上效果是很理想的.
对于Acegi有很多的过滤器不用全写在web.xml里,acegi提供了一个特殊的过滤器我们可以写成这样,在Web.xml里:
代码
  1. filter>
  2. filter-name>Acegifilter-name>
  3. filter-class>org.acegisecurity.util.FilterToBeanProxyfilter-class>
  4. init-param>
  5. param-name>targetClassparam-name>
  6. param-value>org.acegisecurity.util.FilterChainProxyparam-value>
  7. init-param>
  8. filter>
  9. filter-mapping>
  10. filter-name>Acegifilter-name>
  11. url-pattern>/*url-pattern>
  12. filter-mapping>
  13. context-param>
  14. param-name>contextConfigLocationparam-name>
  15. param-value>
  16. /WEB-INF/applicationContext.xml
  17. param-value>
  18. context-param>
  19. listener>
  20. listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  21. listener>
  22. listener>
  23. listener-class>org.springframework.web.util.Log4jConfigListenerlistener-class>
  24. listener>
  25. listener>
  26. listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisherlistener-class>
  27. listener>
  28. servlet>
  29. servlet-name>TestServletservlet-name>
  30. servlet-class>org.li.servlet.TestServletservlet-class>
  31. servlet>
  32. servlet-mapping>
  33. servlet-name>TestServletservlet-name>
  34. url-pattern>/servlet/TestServleturl-pattern>
  35. servlet-mapping>
render_code();
Spring的配置文件里:
代码
  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>
render_code();

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1504132



http://www.niftyadmin.cn/n/599696.html

相关文章

oracle缩表空间大小,在Oracle中查询表的大小和表空间的大小

在Oracle中查询表的大小和表空间的大小有两种含义的表大小。一种是分配给一个表的物理空间数量&#xff0c;而不管空间是否被使用。可以这样查询获得字节数&#xff1a;select segment_name, bytesfrom user_segmentswhere segment_type TABLE;或者Select Segment_Name,Sum(by…

单点登陆系统SSO原理

<iframe align"top" marginwidth"0" marginheight"0" src"http://www.zealware.com/46860.html" frameborder"0" width"468" scrolling"no" height"60"></iframe>本文以某新闻单…

linux 重置oracle密码,【PASSWORD】Linux环境下使用密码验证方式重置SYS用户密码

Linux操作系统&#xff0c;当我们忘记SYS用户名密码又无法通过操作系统验证方式访问数据库时&#xff0c;就需要考虑使用密码验证方式找回SYS用户的密码。本文给出这种方法的实践。1.确保remote_login_passwordfile参数值为“EXCLUSIVE”或“SHARED”sysora10g> show parame…

更改数据库用户的密码(sys,system)

修改系统用户密码&#xff1a;sys,system sqlplus "/as sysdba"SQL> select username,password from dba_users;USERNAME PASSWORD------------------------------ ------------------------------SYS 8A8F025737A9097A…

再谈oracle服务器内存(SGA+PGA+OS)设置

内存结构SGA&#xff08;系统全局区&#xff09;PGA&#xff08;程序全局区&#xff09;SGA&#xff1a;是用于存储数据库信息的内存区&#xff0c;该信息为数据库进程所共享。它包含Oracle 服务器的数据和控制信息,它是在Oracle服务器所驻留的计算机的实际内存中得以分配&…

CAS logout问题释疑

<iframe align"top" marginwidth"0" marginheight"0" src"http://www.zealware.com/46860.html" frameborder"0" width"468" scrolling"no" height"60"></iframe>CAS Logout是一…

最简单的数据库备份脚本

source ~/.bash_profilebackup_path/data/backup/mysql-backupfile_dirname${backup_path}/$(date "%Y-%m")/$(date "%d")mkdir -p ${file_dirname}file_name_库名"库名_"$(date %Y-%m-%d-%T)".sql.gz"/usr/bin/mysqldump -uroot -ppa…

Derby初探

在Java6中&#xff0c;新增加了Derby数据库&#xff0c;一个轻量级的数据库(Apache Database项目的产品)&#xff0c;一个完全基于Java的数据库。相信它的发展应该不错。因为Apache出的产品&#xff0c;一般都表现不错&#xff0c;而且Derby还源于(IBM)CloudSacpe。 使用Derby的…