- 浏览: 43889 次
- 性别:
- 来自: 福州
文章分类
最新评论
在配置Acegi Filter Chain Proxy是设定了targetClass,并制定了其代表的类,并在其他配置文件中声明了其具体的实现。其中实现是通过指定filterInvocationDefinitionSource的。如下:
这里声明了过滤链时需要考虑前后,因为在实现是是从第一个开始的。
也就是说authenticationProcessingFilter是最先触发的,其触发的条件是其URI中是以j_acegi_security_check结尾的。而对于LogoutFilter因为具体实现时它会考虑请求的URI,所以并不是所有的请求都会触发这个过滤器。而rememberMeProcessingFilter并没有任何条件,它的实现如下:
承上说明:自动登录时通过其提供的services进行登录,在登录后返回一个Authentication对象,并通过authenticationManager的校验(认证),判断是否可以通过,如果允许(也就是没有抛出异常)则保存至ServletContextHolder中,并发布成功的事件。否则继续下一个过滤器。
而对于自动登录中的RememberMeServices的实现代码如下:
承上说明:我们采用的是TokenBasedRememberMeServices的实现方式,其主要过程是读取Cookies文件,判断其中是否有Acegi标识的信息,并检验是否过期;并根据用户名和配置的userDetailsService去获取用户的具体信息(判断是否过期、密码是否有效、是否可用等),同时加密后与Cookies中的信息进行对比,判断是否一致。因为每一个session都需要保证如果用户有效,则装配信息,无效的话则需要取消(就是将Cookies设置为null,并返回响应)。做完校验后,把这个userDetail信息绑定到Key对应的键值中,供前面的AuthenticationManager做认证,并把userDetail保存至Request中。
那么就有一个疑问是Cookies的信息是在什么时候保存起来的呢?
这个其实可以先看一下配置信息
以前看别人的示例中并没有加上rememberMeServices,这样是没有办法自动登录的,因为系统提供的默认实现是NullRememberMeServices,并没有保存Cookies信息。
而这边配置的是TokenBasedRememberMeServices实现,其根据提交的参数是否有“_acegi_security_remember_me”选中,若有则保存Cookies。
并且如果注销后则系统将Cookies删除。所以要保证自动登录的话,是不可以点击注销的。
因为在LogoutFilter中的构造器中的Holder中加入了rememberMeServices实现,所以在注销时会调用其logout方法(就是把Cookies设为空并过时的操作),以及其他诸如org.acegisecurity.ui.logout.SecurityContextLogoutHandler的实现,用于清空Session。
<!--****** Fileter Chain ******--> <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=authenticationProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter </value> </property> </bean>
这里声明了过滤链时需要考虑前后,因为在实现是是从第一个开始的。
也就是说authenticationProcessingFilter是最先触发的,其触发的条件是其URI中是以j_acegi_security_check结尾的。而对于LogoutFilter因为具体实现时它会考虑请求的URI,所以并不是所有的请求都会触发这个过滤器。而rememberMeProcessingFilter并没有任何条件,它的实现如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (SecurityContextHolder.getContext().getAuthentication() == null) { //这里是通过rememberMeServices的autoLogin来进行登录作业的,具体的实现方式可查看下一段代码 Authentication rememberMeAuth = rememberMeServices.autoLogin(httpRequest, httpResponse); if (rememberMeAuth != null) { // Attempt authenticaton via AuthenticationManager try { authenticationManager.authenticate(rememberMeAuth); // Store to SecurityContextHolder SecurityContextHolder.getContext().setAuthentication(rememberMeAuth); if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder populated with remember-me token: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( SecurityContextHolder.getContext().getAuthentication(), this.getClass())); } } catch (AuthenticationException authenticationException) { if (logger.isDebugEnabled()) { logger.debug( "SecurityContextHolder not populated with remember-me token, as AuthenticationManager rejected Authentication returned by RememberMeServices: '" + rememberMeAuth + "'; invalidating remember-me token", authenticationException); } rememberMeServices.loginFail(httpRequest, httpResponse); } } chain.doFilter(request, response); } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with remember-me token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } chain.doFilter(request, response); } }
承上说明:自动登录时通过其提供的services进行登录,在登录后返回一个Authentication对象,并通过authenticationManager的校验(认证),判断是否可以通过,如果允许(也就是没有抛出异常)则保存至ServletContextHolder中,并发布成功的事件。否则继续下一个过滤器。
而对于自动登录中的RememberMeServices的实现代码如下:
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { Cookie[] cookies = request.getCookies(); if ((cookies == null) || (cookies.length == 0)) { return null; } for (int i = 0; i < cookies.length; i++) { if (ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY.equals(cookies[i].getName())) { String cookieValue = cookies[i].getValue(); if (Base64.isArrayByteBase64(cookieValue.getBytes())) { if (logger.isDebugEnabled()) { logger.debug("Remember-me cookie detected"); } // Decode token from Base64 // format of token is: // username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key) String cookieAsPlainText = new String(Base64.decodeBase64(cookieValue.getBytes())); String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":"); if (cookieTokens.length == 3) { long tokenExpiryTime; try { tokenExpiryTime = new Long(cookieTokens[1]).longValue(); } catch (NumberFormatException nfe) { cancelCookie(request, response, "Cookie token[1] did not contain a valid number (contained '" + cookieTokens[1] + "')"); return null; } // Check it has not expired if (tokenExpiryTime < System.currentTimeMillis()) { cancelCookie(request, response, "Cookie token[1] has expired (expired on '" + new Date(tokenExpiryTime) + "'; current time is '" + new Date() + "')"); return null; } // Check the user exists // Defer lookup until after expiry time checked, to possibly avoid expensive lookup UserDetails userDetails; try { userDetails = this.userDetailsService.loadUserByUsername(cookieTokens[0]); } catch (UsernameNotFoundException notFound) { cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0] + "' but was not found"); return null; } // Immediately reject if the user is not allowed to login if (!userDetails.isAccountNonExpired() || !userDetails.isCredentialsNonExpired() || !userDetails.isEnabled()) { cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0] + "' but account has expired, credentials have expired, or user is disabled"); return null; } // Check signature of token matches remaining details // Must do this after user lookup, as we need the DAO-derived password // If efficiency was a major issue, just add in a UserCache implementation, // but recall this method is usually only called one per HttpSession // (as if the token is valid, it will cause SecurityContextHolder population, whilst // if invalid, will cause the cookie to be cancelled) String expectedTokenSignature = DigestUtils.md5Hex(userDetails.getUsername() + ":" + tokenExpiryTime + ":" + userDetails.getPassword() + ":" + this.key); if (!expectedTokenSignature.equals(cookieTokens[2])) { cancelCookie(request, response, "Cookie token[2] contained signature '" + cookieTokens[2] + "' but expected '" + expectedTokenSignature + "'"); return null; } // By this stage we have a valid token if (logger.isDebugEnabled()) { logger.debug("Remember-me cookie accepted"); } RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(this.key, userDetails, userDetails.getAuthorities()); auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return auth; } else { cancelCookie(request, response, "Cookie token did not contain 3 tokens; decoded value was '" + cookieAsPlainText + "'"); return null; } } else { cancelCookie(request, response, "Cookie token was not Base64 encoded; value was '" + cookieValue + "'"); return null; } } } return null; }
承上说明:我们采用的是TokenBasedRememberMeServices的实现方式,其主要过程是读取Cookies文件,判断其中是否有Acegi标识的信息,并检验是否过期;并根据用户名和配置的userDetailsService去获取用户的具体信息(判断是否过期、密码是否有效、是否可用等),同时加密后与Cookies中的信息进行对比,判断是否一致。因为每一个session都需要保证如果用户有效,则装配信息,无效的话则需要取消(就是将Cookies设置为null,并返回响应)。做完校验后,把这个userDetail信息绑定到Key对应的键值中,供前面的AuthenticationManager做认证,并把userDetail保存至Request中。
那么就有一个疑问是Cookies的信息是在什么时候保存起来的呢?
这个其实可以先看一下配置信息
<!-- 表单认证处理Filter --> <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager" ref="authenticationManager"></property> <property name="authenticationFailureUrl" value="/acegi_login.jsp?login_error=1"></property> <property name="defaultTargetUrl" value="/userinfo.jsp"></property> <property name="filterProcessesUrl" value="/j_acegi_security_check"></property> <property name="rememberMeServices" ref="rememberMeServices"></property> </bean>
以前看别人的示例中并没有加上rememberMeServices,这样是没有办法自动登录的,因为系统提供的默认实现是NullRememberMeServices,并没有保存Cookies信息。
而这边配置的是TokenBasedRememberMeServices实现,其根据提交的参数是否有“_acegi_security_remember_me”选中,若有则保存Cookies。
并且如果注销后则系统将Cookies删除。所以要保证自动登录的话,是不可以点击注销的。
因为在LogoutFilter中的构造器中的Holder中加入了rememberMeServices实现,所以在注销时会调用其logout方法(就是把Cookies设为空并过时的操作),以及其他诸如org.acegisecurity.ui.logout.SecurityContextLogoutHandler的实现,用于清空Session。
相关推荐
前段时间复习了spring怎么做权限的技术,spring acegi 学习心得.记下来勉励自己.
"学习Acegi-认证(authentication) - Acegi 专栏 - JavaEye知识库.mht"和"Acegi学习小结 - Acegi 专栏 - JavaEye知识库.mht"可能提供了更深入的认证学习材料和作者的学习心得,包括可能遇到的问题和解决方案,这对于...
Acegi 是一个强大的 Java 安全框架,专用于系统安全编程,尤其在处理认证和授权方面表现出色。在本文中,我们将深入探讨 Acegi 的基本概念、如何设置以及它如何与 Spring 框架集成。 首先,让我们了解 Acegi 的核心...
通过学习Acegi,我们可以了解到Web应用安全的基本思路和实践方法,这对于理解现代的Spring Security框架非常有帮助。虽然Acegi已经不再更新,但它的理念和架构仍对现代安全框架设计产生深远影响。
Acegi学习是一个深入探讨Java平台上的安全性框架的主题。Acegi是Spring Framework的早期安全模块,为基于Spring的应用程序提供了强大的身份验证和授权功能。在Java世界中,安全性和权限管理是构建任何企业级应用不可...
这个压缩包包含了Acegi的示例代码和一个学习资源,对于初学者来说是非常宝贵的资料。 首先,让我们深入理解Acegi的核心概念: 1. **身份验证(Authentication)**:Acegi允许你实现自定义的身份验证机制,这包括...
Acegi 是一个在Java开发领域,特别是Spring框架中曾经广泛使用的安全组件,全称为Acegi Security。...学习Acegi可以帮助我们更好地理解Spring Security的工作原理,从而提升我们的应用安全开发能力。
在本文中,我们将深入探讨Acegi的学习指南,通过实例来理解其核心概念和功能。 首先,我们需要了解Acegi的基础概念。Acegi的核心组件包括SecurityContext、Authentication、Authorization和FilterChainProxy。...
由于文章内容是关于acegi pdf学习的参考文档,其中包含了大量关于Acegi安全系统的技术细节,因此以下将详细阐述文档中提及的关键知识点。 首先,Acegi安全系统是一个基于Spring框架的安全解决方案。文档开头简要...
Acegi学习 Acegi是Spring Security的前身,它是一个强大且灵活的安全框架,用于Java企业级应用程序。在本文中,我们将深入探讨Acegi的核心概念、功能以及如何在实际项目中应用它。 首先,我们需要理解Acegi的核心...
### Acegi学习笔记详解 #### 一、Acegi Security概览 **Acegi Security**,作为Spring Security的前身,是一个深度融入Spring Framework的安全框架,它为开发者提供了一套全面的安全解决方案,尤其在Web应用程序中...
AceGI,全称为Acegi ...理解Acegi对于学习和使用Spring Security仍然大有裨益,因为它可以帮助我们更好地理解Web应用程序的安全设计和实现。在实际开发中,掌握Acegi的相关知识可以提升我们构建安全系统的专业能力。
不错的ACEGI 教程
通过深入学习Acegi,你可以了解Spring Security的基本架构和原理,这对于理解现代的Spring Security配置和使用非常有帮助。尽管Acegi已不再更新,但其思想和技术仍在Spring Security中得到沿用和发展。如果你正在...
【Acegi框架介绍 acegi安全与认证】 Acegi Security,现称为Spring Security,是一个强大的安全框架,主要用于基于Spring的企业级应用。它通过Spring的依赖注入(IoC)和面向切面编程(AOP)功能,提供了声明式的...
Spring Acegi是一个安全框架,它为Spring应用提供了一套强大的身份验证和授权机制。这个框架在Spring Security(之前称为Spring Security)之前被广泛使用。在本文中,我们将深入探讨Spring Acegi的核心概念、功能和...
Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...
然而,尽管Acegi非常强大,它也有不足之处,如学习曲线较陡峭,配置复杂,对于初学者来说可能较为困难。此外,随着Spring Security的发展,Acegi的一些功能可能已经被更新的版本替代或优化,因此在使用时需要考虑其...
- **学习曲线**:对于初次接触的开发者而言,Acegi的复杂性和灵活性可能会带来较高的学习成本。 #### 结论 Acegi安全框架凭借其独特的设计和高度的灵活性,成为了Spring框架下处理安全问题的强大工具。通过深入...