解析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是例外,有些部分我还没看明白)。
本文件中包含了DirectX修复工具中一些常见问题及其解答,如您存在问题,请首先查看以下解答是否能解决您的问题。 This file includes some frequently asked questions and answers about DirectX Repair. If you have any problems with the programme, please check first if there are answers below (English translation is at bottom). Thank you. 问题1:XP系统上运行软件时出现0xc0000135的错误,怎么回事? 答:Windows XP SP3系统用户需先安装Microsoft .NET Framework 2.0或更高版本才可运行本程序,详情请见“致Windows XP用户.txt”文件。 问题2:我下载的是标准版或是在线修复版,怎么将程序升级成增强版? 答:首先来说,各个版本之间,主程序(即exe文件)完全相同,标准版与增强版相比,只是缺少相应的扩展数据包,因此无法进行增强式修复(即修复c++)。因此,可以通过补全扩展包的形式使标准版直接成为增强版。本程序自V3.5版起,自带扩展功能。只要在主界面的“工具”菜单下打开“选项”对话框,找到“扩展”标签,点击其中的“开始扩展”按钮即可。扩展过程需要Internet连接,扩展成功后新的数据包可立即生效。扩展用时根据网络速度不同而不同,最快仅需数秒,最慢需要数分钟,烦请耐心等待。 问题3:我的网络连接正常,但为什么扩展总是失败并提示请连接到Internet? 答:这可能是由于扩展过程被电脑上的杀毒软件或防火墙拦截导致的。从V4.0版起针对此问题进行了优化,只需点击“扩展”界面左上角的小锁图标切换为加密链接,即可避免大部分错误。 问题4:我在有的电脑上使用标准版或在线修复版修复DirectX后,程序弹出c++组件仍异常的提示,让我使用增强版再修复;而在有些其他电脑上使用标准版修复完成后,却没有这个提示(此时我感觉c++仍有问题)。这是什么原因? 答:本程序致力于解决0xc000007b错误,因此只有在程序检测到系统中c++存在异常,可能导致0xc000007b问题,而修复时又没有使用增强版修复相应c++时,才会弹出此提示。而对于那些根本没有安装c++的系统,程序则不会提示。理论上讲,本程序完全可以解决c++未安装所带来的任何错误(如提示缺少msvcr140.dll文件等),但之所以程序在这些系统上不做任何提示,是考虑到绝大部分电脑都会缺失c++组件,如果均进行提示,则此提示将变成必出现的提示,所有用户都需要使用增强版进行再次修复,失去了标准版存在的意义。 问题5:部分文件修复失败怎么办? 答:可以以安全模式引导系统(具体方法百度可查),然后再用本程序进行修复即可成功。 问题6:全部文件的状态都是下载失败或失败,这是怎么回事? 答:在极个别的电脑上,由于系统核心组件异常,导致程序在检测时无法调用系统组件而产生此问题。此时请在程序的“工具”菜单下“选项”对话框中,将“安全级别”改为“低”即可。更改后再进行修复即可正确完成相关操作。 问题7:该软件能支持64位操作系统吗? 答:能。程序在编程时已经充分考虑了不同系统的特性,可以完美支持64位操作系统。并且,程序有自适应功能,可以自动检测操作系统版本、位数,无需用户进行设置。 问题8:玩游戏出现闪退、黑屏、卡屏、卡死、帧数低、打太极等问题,修复后仍不能解决? 答:该问题的可能原因较多,比如DirectX有问题,c++有问题。使用DirectX修复工具增强版即可解决由这两种情况所导致的问题。如果修复后仍不能解决,则可能有三种原因:第一,游戏有问题(或破解补丁有问题),建议从别的网站上重新下载;第二,显卡驱动没装好(这种情况较多),建议重装显卡驱动;第三,硬件配置不够。 问题9:出现DirectDraw、Direct3D、AGP纹理加速不可用,修复后仍不能解决? 答:本程序的V3.2版本之后新增了一个开启该加速的功能,请先尝试使用该功能进行修复。如果修复后仍不能解决,则通常是由于显卡驱动有问题造成的,建议到显卡官网下载最新驱动安装即可(如显卡驱动异常,将会在开启DirectX加速页面右上角进行提示,仅限V3.9版或更高版本支持此功能)。 问题10:本程序是只能修复C盘中的DirectX吗?其他盘中的如何修复? 答:本程序不是只能修复C盘中的DirectX,而是修复当前系统所在磁盘的DirectX。如果您的操作系统安装在了C盘,则程序会修复C盘中的DirectX,如果您的操作系统安装在了D盘,则
DirectX修复工具(DirectX repair)是一款完全由本人自主开发的系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。资源中的技术文档包含程序的部分源代码,以供编程爱好者交流。 本程序适用于多个操作系统,如Windows XP(需先安装.NET 2.0,详情请参阅“致Windows XP用户.txt”文件)、Windows Vista以及Windows 7,同时兼容32位操作系统和64位操作系统。本程序会根据系统的不同,自动调整任务模式,无需用户进行设置。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。本程序中包含了最新版的DirectX redist(Jun2010),并且全部文件都有Microsoft的数字签名,安全放心。 本程序为了应对一般电脑用户的使用,采用了傻瓜式一键设计,只要点击主界面上的“检测并修复”按钮,程序就会自动完成校验、检测、修复的全部功能,无需用户的介入,大大降低了使用难度。 本程序采用了多线程编程技术,可充分利用系统的资源,减少时间的等待。同时,针对部分低性能电脑,也做了一定程度的优化。 本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时分析和查找原因,以便找到解决办法。 程序的“选项”对话框中包含了2项高级功能。点击其中的“注册系统中所有dll文件”按钮可以自动注册系统文件夹下的所有dll文件。该项功能不仅能修复DirectX的问题,还可以修复系统中很多其他由于dll未注册而产生的问题,颇为实用。点击第二个按钮可以为dll文件的右键菜单添加“注册”和“卸载”项,方便对单独的dll文件进行注册。请注意,并不是所有的dll文件都可以通过这种方式注册。 程序附带了用户反馈程序,可以在用户允许的前提下发送检测修复结果。用户也可以在出现问题时通过反馈程序和软件作者进行交流,共同查找问题。反馈是完全匿名和自愿的。 本程序基于Microsoft .NET Framework 2.0开发,对于Windows 2000Windows XP、Windows 2003的用户需要首先安装.NET Framework 2.0或更高版本才可运行本程序。有关下载和安装的详细信息请参阅“致Windows XP用户.txt”文件。对于Windows Vista、Windows 7用户,可以直接运行本程序。
Java JDK环境变量配置是为了确保计算机上的Java开发环境正常运行。首先,确保电脑上已经安装了JDK(Java Development Kit),因为JDK是Java的基本运行环境。环境变量是指在操作系统中设置的一些参数,可以用来指定一些程序的运行条件。在配置Java JDK环境变量之前,需要先进行JDK的安装。 JDK的安装分为两个步骤:首先,安装JDK本身;其次,安装JRE(Java Runtime Environment)。请注意,当安装JDK的时候,JRE也会一同安装。在安装JDK的过程中,可以选择安装目录,一般默认为C盘的Java文件夹,但你也可以根据自己的需要修改安装目录。 在完成JDK的安装后,需要配置环境变量。其中最重要的是配置JAVA_HOME和CLASS_PATH两个变量。JAVA_HOME变量指向JDK的安装目录,而CLASS_PATH变量用于指定Java类的搜索路径。 配置JAVA_HOME变量时,将其值设置为JDK的安装目录即可。比如,如果JDK安装在C盘的Java文件夹下,那么JAVA_HOME的值就应该设置为C:\Java。 配置CLASS_PATH变量时,需要将其值设置为以下内容:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar。这些路径将用于指定Java类的搜索路径,以便程序可以正确地找到所需的类文件。 请注意,在配置环境变量时,需要确保使用正确的语法和路径,以免出现错误。完成环境变量的配置后,就可以在计算机上正常运行Java程序了。希望这些信息能对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值