偶对Acegi Security System景仰已久,它利用了Spring提供的IOC和AOP的机制,实现了一个安全架构,让我们的业务逻辑和安全检查逻辑完全解耦,所有的安全逻辑只要通过Spring的标准配置文件的定义就可实现了。不过说得简单,真的每次拿起Acegi Security System来看的时候,感觉就象云里雾里,如果不仔细看它的文档,再深入研究的话,根本就看不出头绪。某种程度上来说,学习Acegi Security System似乎比学习Spring还要难。
最近偶沉下心来,花了好多时间,看了文档和主要的源代码,终于摸出了点头绪。为什么Acegi Security System会这么难?我觉得原因有以下几个:
一、Acegi Security System的配置文件是用的是Spring的标准配置。某种程度上,它的配置是针对Acegi的设计和实现都很了解的人,而不是针对最终用户的。配置文件里那么多的类,那么复杂的对象关联,如果没有对Acegi的设计有深入了解,只能看得云里雾里。也许我们能在Acegi Security上包一层,定义自己的配置文件来简化Acegi Security。但是仔细想想,Acegi Security的设计是有道理的,Security本来就不是一件简单的事,我们不能指望一个新手来完成所有Security的配置。而利用Spring的配置文件却能达到最大的灵活性,利用Spring的IOC机制,所有的配置都可以提供我们的自定义的实现。一旦当我们对Acegi有了深入了解之后,所有的这些配置就会变得很自然了。
二、Acegi的文档相当的好,它将Acegi的内部实现、类之间的关联,实现的目标进行了很深入的分析。但是却忽略了一点,它的整个文档是从设计出发,而不是从需求出发的,整个文档似乎更关注于Acegi Security是怎么设计的,而不是怎么用的。当然我承认如果要深入了解Acegi,我们必须要知道它的设计和实现,但是对于一个新手来说,假如我们能马上知道Acegi的安全认证执行流程是怎么样的,再通过个认证流程展开说明authentication和authorization所涉及到的东西岂不更好?
今天先写到这里啦,过两天再写一下Acegi Security的认证流程吧,还是蛮好玩的,虽然写起来可能会有点累。
我发现我给自己设了个陷阱,对于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' >
<input type='password' >
<input type="submit">
</form>
记住action必须叫j_acegi_security_check,用户名必须叫j_username,密码必须叫j_password。呵呵,代码就不写了,无非就是判断只要Action名字对,就把用户名、密码取出来认证一把,最后把认证成功的Authetication对象填到SecurityContextHolder里再导到相应页面,认证失败就导到出错页面。
呵呵,好了,认证的核心过程其实就这些了,虽然还有其它的好多的Filter和关联,但是当我们把核心的内容分析清楚之后,其它的都不难了。(Authorization是例外,有些部分我还没看明白)。
- 大小: 70 KB
- 大小: 22.3 KB
分享到:
相关推荐
《Acegi Security 1.0.7:Spring框架的安全认证组件深度解析》 Acegi Security是Spring框架的一个扩展,专为Java企业级应用提供安全认证和授权服务。它在Spring框架的基础上构建了一套完整的安全解决方案,使开发者...
标题和描述均提到了“Acegi Security整合CAS实例”,这涉及到Spring Framework下的Acegi Security模块与CAS(Central Authentication Service)的集成。Acegi Security是Spring框架的一个子项目,旨在为应用提供安全...
Acegi Security是一个经典的Java安全框架,它为Spring应用提供了全面的安全管理服务。在这个" Acegi-security-samples-tutorial-1.0.7.zip "压缩包中,包含了一个详细的教程实例,帮助开发者理解并掌握Acegi ...
接着,手册会详细解析Spring Security的配置,包括XML配置和Java配置两种方式。通过配置,开发者可以定义访问控制规则,比如哪些URL需要用户登录后才能访问,哪些操作只能由具有特定角色的用户执行。此外,手册还会...
### Spring Security 3.0.1 中文版知识点解析 #### 一、Spring Security 3.0.1 概览 ##### 1.1 Spring Security 是什么? Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架。它提供了许多功能...
在Spring框架中,Acegi(现在已经并入Spring Security)是一个强大的安全管理组件,它提供了认证和授权功能。在本文中,我们将深入探讨Spring_Acegi框架如何实现授权机制,特别是通过`FilterSecurityInterceptor`来...
本文将重点解析Acegi Security中的各个过滤器,这些过滤器在保护应用程序的安全方面起着至关重要的作用。 首先,我们要了解过滤器在Web应用中的角色。在HTTP请求被传递到Servlet容器之前,过滤器可以对请求进行...
在本文中,我们将深入探讨Acegi Security的核心概念,并通过SpringSide项目中的`applicationContext-acegi-security.xml`配置文件来解析其工作原理。 一、Acegi Security概述 Acegi Security(现已被Spring ...
### Spring Security 官方文档中文版重要知识点解析 #### 一、Spring Security 概述 **1.1 Spring Security 是什么?** Spring Security 是一款基于 Spring 框架的安全插件,提供了完整的安全性解决方案,包括...
Acegi 是一个在Java开发领域,特别是Spring框架中曾经广泛使用的安全组件,全称为Acegi Security。这个系统为Spring应用程序提供了全面的安全管理解决方案,包括身份验证、授权、会话管理以及安全事件处理等功能。...
至于标签“源码”和“工具”,意味着可能在博文中会有源代码示例和对Acegi Security这个工具的深入解析。源码分析有助于理解框架内部的工作机制,而工具则强调了Acegi Security作为一个方便的开发工具的角色。 不过...
6. **源码解析**: 分析Acegi Security的源码可以帮助理解其内部工作机制,包括token的生成、验证流程,以及与Spring Security的交互。 7. **工具支持**: 可能涉及到的工具可能包括IDE(如IntelliJ IDEA或Eclipse)...
以下将基于给定的部分内容,深入解析Spring Security 2的重要知识点。 ### Acegi2.0简介 Spring Security 2实际上是在Acegi Security的基础上发展而来的,Acegi2.0是Spring Security的一个前身版本。它引入了一...
Spring Security是基于Spring框架的安全组件,原名为Acegi Security。它为Web应用程序提供了全面的安全服务,包括认证、授权、会话管理以及防止常见攻击(如CSRF、XSS等)。Spring Security通过高度可配置的API,使...
1. **配置Acegi Security**:首先,我们需要在Spring配置文件中启用Acegi Security,并配置相关的安全设置,如用户名密码认证器、权限解析器等。这通常涉及`<bean>`标签的定义,例如`authentication-manager`、`user...
这篇博客将深入解析一个配置了Acegi Security的`applicationContext-acegi-security.xml`文件,帮助我们理解如何将LDAP与Acegi集成以实现更安全的Web应用。 **LDAP基础** LDAP是一种标准的网络协议,用于存储和...
《Spring Security 2.0深度解析》 Spring Security是一款强大的安全框架,用于处理Java应用程序的安全需求,特别是Web应用。在2.0版本中,它提供了更完善的授权、认证机制,以及对Spring生态系统的深度集成。本文将...