- 浏览: 152320 次
- 性别:
- 来自: 武汉
-
最新评论
-
damoqiongqiu:
为神马文档没有离线下载的,求离线的文档,求楼主赐文档:2534 ...
AsWing 入门 -
afeng119:
谢谢,试试好用不!
struts的html:file标签上传文件,中文的文件名会导致乱码问题 -
wenjinglian:
那去用用
JAVA MYSQL做分页 -
zltian:
AsWing 入门 -
毛冬:
呵呵。就是說LIST是對象引用,而不是值引用
JAVA LIST MAP 是引用地址而不是复制
我发现我给自己设了个陷阱,对于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是例外,有些部分我还没看明白)。
虽然我不想介绍太多与安全认证流程无关的东西,但是有些东西的讲解却是必不可少的,因为没有这些基本的概念和类,后面的东西就没法说清了。不过对于具体的类、类图和它们之间的关联,我还是推荐去看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是例外,有些部分我还没看明白)。
发表评论
-
动易标签大全
2009-06-24 13:08 2758网站通用标签适用于整 ... -
JAVA LIST MAP 是引用地址而不是复制
2009-03-10 10:36 4040StringBuffer aa=new StringBuffe ... -
取得上1次等入的session
2009-03-10 10:25 1556前言作为J2EE的重要组成部分的jsp和servlet规范中, ... -
JAVA 自定义标签 简介
2009-01-20 16:19 2371Test.jsp <!DOCTYPE HTML P ... -
无级栏目
2009-01-07 17:32 1294很早以前写的东西 这2天要用找了我10几分中 放上来做个笔记 ... -
excel导出文件
2009-01-06 15:48 1656// 创建一个新的excel文件,并将数据导入进去 publ ... -
图片光标定位
2008-12-24 17:25 1606<form action="2.jsp ... -
JAVA导出EXCEL
2008-12-19 10:29 3335Vector vector=listSparepart(con ... -
JAVA 读写文件
2008-11-14 09:44 1594public static void main(String ... -
img图片没找到onerror事件
2008-11-12 15:50 2945<script type="text/java ... -
HTMLArea onsubmit 提交验证问题
2008-10-31 11:21 1471在JSP中用上了HTMLArea后发现里边有个ONSUBMIT ... -
radio JS验证
2008-10-29 17:03 1509function checked(){ var isJu ... -
JAVA读文件夹
2008-10-28 09:05 2407public static boolean readfi ... -
java md5类
2008-10-16 16:00 3743public static String getMD5(byt ... -
DWR写个3级联动
2008-09-18 10:08 1562我原先写过1个拿prototype.js写过1个 可惜和htm ... -
添加时间的JS
2008-09-11 11:28 1075他同学小小那边有份 可惜他那个我用的时候JS 总在暴错 以前我 ... -
总结:子窗口创建及父窗口与子窗口之间通信
2008-09-05 16:46 35361、Javascript弹出子窗口 可以通过多种方式实现,下面 ... -
反射写SQL语句
2008-08-26 15:54 1023// 改 // public void update(Obj ... -
JAVA mysql插入时间
2008-08-21 10:18 3613MYSQL为DATATIME型的时候 pstmt.setTim ... -
java mysql批量导入优化
2008-08-08 09:18 2481Connection conn=dao.getConn(); ...
相关推荐
### Acegi Security System for Spring:全面解析与应用 #### 一、引言 在现代企业级应用程序开发中,安全是至关重要的一个方面。无论是互联网银行应用还是内部电话簿系统,都需要不同程度的安全保护措施来确保...
Acegi是一个专门为SpringFramework提供安全机制的项目,全称为Acegi Security System for Spring.
Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...
Spring Security(以前称为Acegi Security)现在托管在Spring Framework网站上:http://www.springframework.org/spring-security/
Acegi Security System for Spring Acegi Security是一款针对Spring框架的安全组件,它提供了全面的身份验证、授权和服务层安全功能。在深入探讨Acegi Security的源码之前,我们需要了解一些基本概念和背景知识。 ...
Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...
Acegi Security System for Spring由Carlos Sánchez González撰写,重点阐述了如何在Java应用程序中采用面向切面编程(AOP)特性来实现安全机制,而不会对开发人员造成额外的编码负担。这主要得益于Spring框架提供...
它最初是Acegi Security System for Spring的一个后继产品,提供了身份验证和授权机制,可以应用于Web层、方法层和访问服务层。 2. Spring Security的历史和版本: Spring Security的历史可以追溯到2003年,当时它...
Acegi Security System 是一个强大的安全框架,专为Spring框架设计,但也可应用于任何Java应用程序。它解决了企业级应用程序中常见的安全问题,如数据验证和身份验证。Acegi通过一组可配置的安全过滤器来实现这些...
Acegi是Spring框架早期的一个安全模块,全称为Acegi Security System for Spring,它为Spring应用程序提供了全面的安全管理功能。在2008年,Acegi被整合到Spring Security(原名Spring Security 2.0)中,成为其核心...
Spring Security (Acegi Security System for Spring) 示例来自 Mike Wiesner,entwickler.press 的“Spring Security - Das Acegi Security System Professionalell einsetzen”一书中使用的示例
- **历史背景**:Spring Security起源于2003年,最初名为“Acegi Security System for Spring”,简称“Acegi Security”。在Ben Alex的领导下逐渐发展成为一个复杂的认证和访问控制系统,并被广泛采纳为Spring ...
从它的起源来看,SpringSecurity的前身是2003年底由Spring开发者邮件列表中提出的安全需求而启动的项目,最早以“The Acegi Security System for Spring”之名出现。2004年,随着社区的支持和增长,该项目在...
首先,Spring Security原先是Acegi Security System for Spring项目的一个后续者,它被广泛地接受,并且在众多企业级项目中作为安全解决方案。Spring Security提供了全面的安全服务,支持多种认证机制,并能够与...
它的历史可以追溯到Acegi Security System for Spring,这是一个用于Spring框架的早期安全库。随着版本的迭代,Spring Security不断完善和更新,逐步发展成为一个功能强大的安全框架。 关于Spring Security的版本...
Acegi Security System for Spring 是一个历史悠久的Java安全框架,它为Spring应用提供了全面的安全管理解决方案。这个框架的主要目标是提供一套灵活、可扩展且易于使用的工具,帮助开发人员实现复杂的身份验证、...
最初由 Ben Alex 在 2003 年创建,名为 "The Acegi Security System for Spring" 或简称 "Acegi Security"。随着时间的发展,它逐渐演变成为 Spring 生态系统中的标准安全解决方案,并被广泛应用于基于 Spring 的...
Acegi Security System是Spring Security的前身,它是一个用于Java企业级应用的安全框架,提供了一整套强大且灵活的安全控制机制。在深入探讨Acegi的知识点之前,先了解一下它为何重要。在开发复杂的Web应用程序时,...