`

菜鸟-手把手教你把Acegi应用到实际项目中(3)

阅读更多

        这一节我们将要了解的是AnonymousProcessingFilter、RememberMeProcessingFilter和LogoutFilter三个过滤器。

 

1、AnonymousProcessingFilter

       在大部分企业应用中,存在许多不需要用户登录就可以访问的资源,比如登录页面、退出页面、主页等。鉴于此,Acegi提供了匿名认证服务。这样能够使所有的Web资源得到保护,而不是某些资源不设权限控制,让任何人都可以访问,这样整个Acegi使能应用的Web安全策略模型将非常完美。与此同时,SecurityContextHolder(SecurityContext)将始终持有Authentication对象,因此代码的健壮性、可读性也将得到增强。

       AnonymousProcessingFilter,该过滤器是用来对匿名用户的处理。如果用户尚未登录,将生成一个匿名用户的Authentication存放到ContextHolder中。即当不存在任何授权信息时,自动为Authentication对象添加userAttribute中定义的匿名用户权限。

<bean id="anonymousProcessingFilter"
	class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
	<property name="key" value="changeThis" />
	<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS" />
</bean>

       

 

 

 

说明:

l         key:用于指定用户的名称,其实这个属性指定的值只是一个简单的标识符,可以自己取值。

l         userAttribute:用于指定匿名用户的密码(anonymousUser)、权限信息(ROLE_ANONYMOUS)和启用状态(enabled/disabled),这里anonymousUser实际上是用户名。

 

        另外,和AuthenticationProcessingFilter的一样,AnonymousProcessingFilter也有自己的AuthenticationProvider,即AnonymousProcessingFilter。

<bean
	class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
	<property name="key" value="changeThis" />
</bean>

 

 

 

 

      此处的key一般与AnonymousProcessingFilter中的key保持一致,用于保证Authentication对象的真实性,当然这只是Acegi内部的一个设计细节,开发者直接提供自身的key属性取值即可。同样将该Provider加到authenticationManager的providers属性列表中。(个人发现,如果不提供AnonymousAuthenticationProvider,同样能实现匿名认证的功能,或者key不相同也没影响,这一点本人暂时不太明白,如果有谁清楚的请留言给我,谢谢^_^)

 

2、RememberMeProcessingFilter
        该Filter会在用户登录后,在本地机器上记录用户cookies信息,这样下次访问就不用再登录了。它还负责对所有HTTP请求进行拦截,当发现SecurityContextHolder中没有包含有效的Authentication对象时,自动调用RememberMeServices#autoLogin()方法从Cookie中获取用户名/密码的编码串进行自动登录,所以rememberMeProcessingFilter首先要注入一个RememberMeServices Bean。
rememberMeProcessingFilter通过rememberMeServices获取对应Cookie中用户的UserDetails后,就必须进行用户身份认证。这项工作依然委托给authenticationManager完成,所以我们给rememberMeProcessingFilter注入了authenticationManager Bean。
       authenticationManager如何对基于Cookie的用户凭证进行认证呢?显然,不能采用原来的daoAuthenticationProvider所用的方法,因为Cookie所提供用户凭证和登录表单提供的用户凭证在格式上存在很大的差异。基于Remember-Me的用户名/密码信息是经过特殊编码的字符串,Acegi通过RememberMeAuthenticationProvider负责对基于Cookie的用户凭证信息进行认证。所以你必须将该认证提供者添加到authenticationManager中。

<bean id="rememberMeProcessingFilter"
	class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
	<property name="authenticationManager" ref="authenticationManager" />
	<property name="rememberMeServices" ref="rememberMeServices" /><!-- 增加 -->
</bean>
<bean id="authenticationManager"
	class="org.acegisecurity.providers.ProviderManager">
	<property name="providers">
		<list>
			<ref local="daoAuthenticationProvider" />
			<!-- 增加 -->
			<bean
				class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
				<property name="key" value="changeThis" />
			</bean>
			<!-- 增加 -->
			<bean
				class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
				<property name="key" value="foobar" /><!-- key必须和rememberMeServices中的key一致 -->
			</bean>
		</list>
	</property>
</bean>
<!-- 增加, 默认tokenValiditySeconds = 1209600L, 即保留两周 -->
<bean id="rememberMeServices"
	class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
	<property name="userDetailsService" ref="inMemDaoImpl" />
	<!-- cookie中的键值, 防止保存到客户端的cookie中的加密串被恶意篡改 -->
	<property name="key" value="foobar" />
	<!-- cookie有效时间, 单位为秒, 这里设定为5天内不用再登陆 -->
	<property name="tokenValiditySeconds" value="432000" />
</bean>
另外,必须在AuthenticationProcessingFilter中加入rememberMeServices。这样,当用户勾选了记住密码并登录后,rememberMeServices会将用户信息保存到Cookie中
<bean id="authenticationProcessingFilter"
	class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
	……
	<property name="rememberMeServices" ref="rememberMeServices" /><!-- 增加, 可别忘了此处 -->
</bean>

 

 

 

 

3、LogoutFilter
        该Filter负责处理退出登录后所需要的清理工作。包括:
1) 销毁session
2) 清空 ContextHolder
3) 把rememberMeServices从cookies中清除掉
4) 最后重定向到指定的退出登陆页面。

<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/index.jsp"/> <!-- URL redirected to after logout 退出页面url -->
      <constructor-arg>
         <list>
              <ref bean="rememberMeServices"/><!-- 用于清空cookies -->
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
         </list>
      </constructor-arg>
</bean>

 

 

 

 

        最后,请注意,Acegi默认的自动登陆设定参数名为_acegi_security_remember_me,注销链接为/j_acegi_logout。
        登录时,在页面添加以下代码:

 

<input type="checkbox" name="_acegi_security_remember_me">

 

 

        退出时,在页面添加以下代码:

 

<a href="<%=request.getContextPath() %>/j_acegi_logout">Logout</a>

 

 
 

 

开发环境:

MyEclipse 5.0GA

Eclipse3.2.1

JDK1.5.0_10

tomcat5.5.23

acegi-security-1.0.7

Spring2.0

 

Jar包:

acegi-security-1.0.7.jar

Spring.jar

commons-codec.jar

jstl.jar (1.1)

standard.jar

 

 

 

 

 

分享到:
评论
12 楼 iloveyoo 2010-07-02  
楼主这里acegi介绍的挺全面,通俗易懂,acegi里面还有一个acl的控制,能够控制用户访问部分数据,如用户A只能访问一部分订单,用户B只能访问另一部分订单,这个也补充上就更全面。mail:ma_yaling1013@hotmail.com
11 楼 iloveyoo 2010-07-01  
lz,正在学习acegi,这里有点疑问,rembermefilter是为了保持cookie多长时间内不失效,下次不用再登陆,如例子5天;而LogoutFilter又在退出时清空cookie是否矛盾呢?mail:ma_yaling1013@hotmail.com
10 楼 javaliver 2010-05-28  
用户验证成功后访问/authenticate/index.jsp 没有问题
没有验证直接访问/authenticate/index.jsp 报如下问题新手
org.acegisecurity.AccessDeniedException: Access is denied
at org.acegisecurity.vote.AffirmativeBased.decide(AffirmativeBased.java:68)
at org.acegisecurity.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:285)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:104)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:217)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:229)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:274)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:148)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:619)
9 楼 adamzzww 2009-07-28  
http://localhost:8080/Acegi2/authenticate/index.jsp
windywindy 写道
严重: Servlet.service() for servlet default threw exception
java.lang.NoClassDefFoundError: org/springframework/web/bind/RequestUtils
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.rememberMeRequested(TokenBasedRememberMeServices.java:360)
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.loginSuccess(TokenBasedRememberMeServices.java:366)
at org.acegisecurity.ui.AbstractProcessingFilter.successfulAuthentication(AbstractProcessingFilter.java:488)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:266)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source
登陆时报这个错误!
我用的spring的包和前面2个工程一样的!spring-framework-2.5.6

网上搜的,加个spring-webmvc看看,我的可以了。希望楼主,发个原配JAR,或者有空跟新下版本?
PS:初学,比较麻烦,看了LZ的连载,很有收获。谢谢..
8 楼 windywindy 2009-07-28  

1、AnonymousProcessingFilter
       在大部分企业应用中,存在许多不需要用户登录就可以访问的资源,比如登录页面、退出页面、主页等。鉴于此,Acegi提供了匿名认证服务。这样能够使所有的Web资源得到保护,而不是某些资源不设权限控制,让任何人都可以访问,这样整个Acegi使能应用的Web安全策略模型将非常完美。与此同时,SecurityContextHolder(SecurityContext)将始终持有Authentication对象,因此代码的健壮性、可读性也将得到增强。
       AnonymousProcessingFilter,该过滤器是用来对匿名用户的处理。如果用户尚未登录,将生成一个匿名用户的Authentication存放到ContextHolder中。即当不存在任何授权信息时,自动为Authentication对象添加userAttribute中定义的匿名用户权限。
Xml代码
windywindy 写道
严重: Servlet.service() for servlet default threw exception
java.lang.NoClassDefFoundError: org/springframework/web/bind/RequestUtils
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.rememberMeRequested(TokenBasedRememberMeServices.java:360)
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.loginSuccess(TokenBasedRememberMeServices.java:366)
at org.acegisecurity.ui.AbstractProcessingFilter.successfulAuthentication(AbstractProcessingFilter.java:488)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:266)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source
登陆时报这个错误!
我用的spring的包和前面2个工程一样的!spring-framework-2.5.6

原来spring2.5把2.1中有的org.springframework.web.bind包去掉了,郁闷,高版本反而不兼容!
7 楼 windywindy 2009-07-27  
严重: Servlet.service() for servlet default threw exception
java.lang.NoClassDefFoundError: org/springframework/web/bind/RequestUtils
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.rememberMeRequested(TokenBasedRememberMeServices.java:360)
at org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.loginSuccess(TokenBasedRememberMeServices.java:366)
at org.acegisecurity.ui.AbstractProcessingFilter.successfulAuthentication(AbstractProcessingFilter.java:488)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:266)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source
登陆时报这个错误!
我用的spring的包和前面2个工程一样的!spring-framework-2.5.6
6 楼 major361 2009-04-02  
ikon 写道

RememberMeProcessingFilter 不起作用

你是不是没有勾选
<checkbox name="_j_acegi_remember_me" />
5 楼 20244806 2009-03-13  
@ikon

你看到RememberMeProcessingFilter 不起作用的原因,估计是你的web.xml里面那个welcome-file-list配置的是login.jsp这个页面
4 楼 zhanjia 2008-11-07  
ikon 写道

RememberMeProcessingFilter 不起作用

这位朋友, 我刚测试过是可以的.
登录时选中:五天内不用登录
关闭浏览器后, 直接输入:http://localhost:8080/Acegi2/authenticate/index.jsp可以访问而不用登录
3 楼 ikon 2008-11-07  
RememberMeProcessingFilter 不起作用
2 楼 ikon 2008-11-07  
自动登陆是不可以的
1 楼 zhanjia 2008-10-20  
我要重新编辑字体,因为字体太难看,但一编辑那些用HTML、XML嵌入的代码又得重新做一次,好麻烦,不然就乱了
熟悉javaeye的朋友请教一教我,谢谢了!

相关推荐

Global site tag (gtag.js) - Google Analytics