`
xi5566
  • 浏览: 152320 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

解析Acegi Security System for Spring(转载)

阅读更多
我发现我给自己设了个陷阱,对于Acegi Security System的解析并不是光写个安全认证的流程就能说清楚的。虽然看起来Acegi的文档确实挺累,但是当我动笔写时却发现要写得比这个文档更好还是挺难的。毕竟我们不能让本来很难的事情一下子就变得很简单了,我也是昨天重要看了一遍了Acegi Security System的源代码,才发现我自己有明白了好多不明白的东西。但是我仍然希望我写的东西能够帮助那些正在学习和研究Acegi Security System的人们,所以我又开始动笔了,呵呵!



虽然我不想介绍太多与安全认证流程无关的东西,但是有些东西的讲解却是必不可少的,因为没有这些基本的概念和类,后面的东西就没法说清了。不过对于具体的类、类图和它们之间的关联,我还是推荐去看Professional Java Development with the Spring Framework里关于Acegi的那一章,对于想读Acegi的源代码和了解Acegi内部设计的人来说,这一章真是太有用了。





本来不想贴这幅类图的,毕竟有盗版的嫌疑,但是发现有些东西不贴出来又说不清楚。整个认证功能的核心是Authentication接口,我们只把Authentication想象成一个包含用户基本信息的类就行了,它里面放了用户名、密码、这个用户的具体权限有哪些(当然具体的东西是由它的子类UsernamePasswordAuthenticationToken实现的,其它类的存放的信息稍有不同,毕竟验证的方式还是多种多样的,我这里描述的所有东西Acegi最常用的实现方式,而不考虑其它的东西,否则只会分散注意力,看了之后一头雾水)。Authentication里还包含了一个GrantedAuthority接口,今天暂且不讨论Authorization的问题了,毕竟它与验证的流程是不相关的,而具体的细节又极复杂。



我们通过AuthenticationManager这个接口来验证这个Authtication对象的合法性,真正的验证过程看上去很悬,其实最后的实现无非是去数据库搜索一下是否存在这个用户,密码是否匹配(说的仍然是最常用的实现方式,呵呵),只是它设计的时候对象的关联比较巧妙,类图看熟了就会觉得没什么,真正查数据库的那个类是DaoAuthenticationProvider。这个接口真正巧妙的地方是它执行后返回的结果是一个Authentication,而不是用一个布尔值来表示验证成功或失败。Why? 记得当年在JavaEye上有个讨论Exception的贴子,robbin认为用户安全认证应该用Checked Exception来控制流程,更多的人认为密码错误是正常的事件流,返回布尔值更为恰当,这里不讨论这两种观点的对错,毕竟每个人站的角度不同,具体的情况也不同。



但是如果要实现认证的透明性,我们要用到的却是unchecked exception,这个Exception叫做AuthenticationException(如果是authorization会抛出AccessDeniedException,不过道理类似),这真是奇妙的事,因为Exeception是可以传递的,如果在本类里面处理不了这个Exception,我们就会将这个Exception抛给调用这个类的类,如此循环,直到有一个类可以处理它为止(对于Web来说应该是在页面上提示登录出错信息)。没想到Exception的这个种特性用在安全认证里如此的合适,权限不够?用户密码不对?我才不管呢,只要抛出个异常,最后会有人把它接住处理掉的。当然这里的另一个条件是Unchecked,只有unchecked才不会导致接口的污染,才能达到完全的透明性。



有了前面的基础接口,我们要提出下一个问题了,这个Authentication对象应该存放在哪里?几乎每个做过Web应用的人告诉我:HttpSession。Acegi也不例外,虽然还有其它的存放地点(要跟具体的Web容器结合,会导致不兼容性,一般不提倡用)。但是我们马上会问下一个问题:我们怎么得到Authentication对象?当然我们可以去HttpSession里去取,但是很多时候我们在验证的是与Web层无关的(比如要用户调用Service层的权限或Domain Object的权限)。我们必须用与Web无关的API来获取Authentication。这让我们想起了什么?对,是Webwork,Webwork的Action是完全与Web API无关的,它的Request里的参数自动populate成了Action的属性,但是我们仍然可以通过ActionContext来获取这些信息。它是怎么做到的?是Threadlocal,因为每个Web Request都会使Web容器生成一个新的线程来处理它的这个特性使我们可以将这些Web的数据一股脑塞给Threadlocal。这个存放Authentication的对象叫做SecurityContext,而把SecurityContext放入Threadloal或取出的则是SecurityContextHolder,下面就是它的类图:





讲完这些基础设施,我们就可以看具体的认证流程啦,真正的认证是一串的Filter(对Servlet容器熟悉的人应该都不要解释了)。只不过Acegi在这些Filter上稍微玩的点花招,因为一般的Filter是不能定义在Spring的ApplicationContext里的,所以这用了一个代理的Filter对象FilterToBeanProxy将Filter操作Delegate给定义在ApplicationContext里的Filter。这个似乎跟主题无关,不过如果以后真有类似的需求的话,这倒是蛮管用的一招。当然还有FilterChainProxy,它把一串的Filter全部定义在一个bean里,使配置简化了好多,呵呵。



我们来看看Filter的一头一尾。头是httpSessionContextIntegrationFilter,其实它的功能前面已经讨论过了,在执行前把HttpSession里的Authentication取出来放到SessionContextHolder(Threadlocal)里,在执行完毕后,把Authentication塞回到HttpSession。真正的实现代码有一堆,不过核心的代码无非就这么几行:

Object contextFromSessionObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY);

SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);

chain.doFilter(request, response);

httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,,SecurityContextHolder.getContext());



Filter的尾是securityEnforcementFilter,它的工作就是进真正的用户认证的流程控制了,具体的认证工作它会delegate给FilterSecurityInterceptor,但是不管怎么认证,结果无非是认证成功或失败,securityEnforcementFilter只要管抓住异常再转到特定的页面就行了。下面就是这个类的信心代码:

try {

filterSecurityInterceptor.invoke(fi);

}

} catch (AuthenticationException authentication) {

sendStartAuthentication(fi, authentication);

} catch (AccessDeniedException accessDenied) {

sendAccessDeniedError(fi, accessDenied);

}



我们再来看看用户登录是怎么干的吧。Acegi的用户登录很有意思,为了不让用户写任何这方面的代码,它也直接把这个功能放到Filter里了,这个Filter叫做authenticationProcessingFilter。这个Filter的要求是页面上的form的Action名字,登录名、密码的字段名都是定死的。一个简单的页面就这些啦:

<form action="<c:url value=' j_acegi_security_check '/>" method="POST">

<input type='text' name='j_username'>

<input type='password' name='j_password'>

<input name="submit" type="submit">

</form>

记住action必须叫j_acegi_security_check,用户名必须叫j_username,密码必须叫j_password。呵呵,代码就不写了,无非就是判断只要Action名字对,就把用户名、密码取出来认证一把,最后把认证成功的Authetication对象填到SecurityContextHolder里再导到相应页面,认证失败就导到出错页面。



呵呵,好了,认证的核心过程其实就这些了,虽然还有其它的好多的Filter和关联,但是当我们把核心的内容分析清楚之后,其它的都不难了。(Authorization是例外,有些部分我还没看明白)。

分享到:
评论

相关推荐

    Acegi Security System for Spring

    ### Acegi Security System for Spring:全面解析与应用 #### 一、引言 在现代企业级应用程序开发中,安全是至关重要的一个方面。无论是互联网银行应用还是内部电话簿系统,都需要不同程度的安全保护措施来确保...

    acegi-security-cas-1.0.7.jar

    Acegi是一个专门为SpringFramework提供安全机制的项目,全称为Acegi Security System for Spring.

    实战Acegi:使用Acegi作为基于Spring框架的WEB应用的安全框架

    Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...

    Acegi Security System for Spring-开源

    Spring Security(以前称为Acegi Security)现在托管在Spring Framework网站上:http://www.springframework.org/spring-security/

    acegi-security源码包

    Acegi Security System for Spring Acegi Security是一款针对Spring框架的安全组件,它提供了全面的身份验证、授权和服务层安全功能。在深入探讨Acegi Security的源码之前,我们需要了解一些基本概念和背景知识。 ...

    实战Acegi_使用Acegi作为基于Spring框架的WEB应用的安全框架

    Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...

    SeguridadnointrusivaSpring

    Acegi Security System for Spring由Carlos Sánchez González撰写,重点阐述了如何在Java应用程序中采用面向切面编程(AOP)特性来实现安全机制,而不会对开发人员造成额外的编码负担。这主要得益于Spring框架提供...

    spring security reference【洋文】

    它最初是Acegi Security System for Spring的一个后继产品,提供了身份验证和授权机制,可以应用于Web层、方法层和访问服务层。 2. Spring Security的历史和版本: Spring Security的历史可以追溯到2003年,当时它...

    acegisecurity

    Acegi Security System 是一个强大的安全框架,专为Spring框架设计,但也可应用于任何Java应用程序。它解决了企业级应用程序中常见的安全问题,如数据验证和身份验证。Acegi通过一组可配置的安全过滤器来实现这些...

    acegi——笔记学习

    Acegi是Spring框架早期的一个安全模块,全称为Acegi Security System for Spring,它为Spring应用程序提供了全面的安全管理功能。在2008年,Acegi被整合到Spring Security(原名Spring Security 2.0)中,成为其核心...

    Spring Security Samples-开源

    Spring Security (Acegi Security System for Spring) 示例来自 Mike Wiesner,entwickler.press 的“Spring Security - Das Acegi Security System Professionalell einsetzen”一书中使用的示例

    spring security 3

    - **历史背景**:Spring Security起源于2003年,最初名为“Acegi Security System for Spring”,简称“Acegi Security”。在Ben Alex的领导下逐渐发展成为一个复杂的认证和访问控制系统,并被广泛采纳为Spring ...

    SpringSecurity课程文档.pdf

    从它的起源来看,SpringSecurity的前身是2003年底由Spring开发者邮件列表中提出的安全需求而启动的项目,最早以“The Acegi Security System for Spring”之名出现。2004年,随着社区的支持和增长,该项目在...

    spring-security-reference.pdf

    首先,Spring Security原先是Acegi Security System for Spring项目的一个后续者,它被广泛地接受,并且在众多企业级项目中作为安全解决方案。Spring Security提供了全面的安全服务,支持多种认证机制,并能够与...

    spring security reference 3.1.6 使用指南

    它的历史可以追溯到Acegi Security System for Spring,这是一个用于Spring框架的早期安全库。随着版本的迭代,Spring Security不断完善和更新,逐步发展成为一个功能强大的安全框架。 关于Spring Security的版本...

    Acegi中文参考手册

    Acegi Security System for Spring 是一个历史悠久的Java安全框架,它为Spring应用提供了全面的安全管理解决方案。这个框架的主要目标是提供一套灵活、可扩展且易于使用的工具,帮助开发人员实现复杂的身份验证、...

    spring security3配置和使用

    最初由 Ben Alex 在 2003 年创建,名为 "The Acegi Security System for Spring" 或简称 "Acegi Security"。随着时间的发展,它逐渐演变成为 Spring 生态系统中的标准安全解决方案,并被广泛应用于基于 Spring 的...

    Acegi参考资料

    Acegi Security System是Spring Security的前身,它是一个用于Java企业级应用的安全框架,提供了一整套强大且灵活的安全控制机制。在深入探讨Acegi的知识点之前,先了解一下它为何重要。在开发复杂的Web应用程序时,...

Global site tag (gtag.js) - Google Analytics