首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Acegi源码研究(五):七剑上天山

2012-11-10 
Acegi源码研究(五):七剑下天山???? 在Acegi初体验及初解剖(http://rmn190.iteye.com/blog/332711)里,通过

Acegi源码研究(五):七剑下天山

???? 在Acegi初体验及初解剖(http://rmn190.iteye.com/blog/332711)里,通过对web.xml和applicationContext-acegi-security.xml的跟踪,我们得出被Acegi拦截下的请求最终交到了filterInvocationDefinitionSource配置下的几个Filter的实现类来处理. 它们是怎么处理这个请求的呢? 在Acegi(三): Acegi? Who are you?,我们听说江湖中有"七剑", 但这么久了"七剑"怎么还没露面呢? 这篇博客中我们将看到下天山的"七剑".

??? 首先我看下都有哪些Bean参于了Acegi的保卫工作, 如下图所示:

??? Acegi源码研究(五):七剑上天山

上面是静态的定义, 再看下图的动态调用图:

Acegi源码研究(五):七剑上天山

?

这里结合着上图,我们跟着浏览器发出的请求走一遍.
?? ?Step1: 对上就上图中数字1,这里浏览器发出一个请求.
?? ?Step2: Web服务器,我们这里的Tomcat接受到Step1发来的HTTP请求, 把里面的信息抽取出来,组装成一个Request对象, 同时Tomcat也生成了一个Response对象,这样接下的Request穿过的Filter都有机会来修改这个Response对象了,也正是Acegi抓住了这个机会利用Filter来改变Response里的值达到保护我们系统的作用.这里Request到达图中的"Filterchain proxy", 我们还记得web.xml中配置的"FilterToBeanProxy"及基配置参数FilterChainProxy(targetClass的值), 再看Bean图中的filterChainProxy,这里我们动态地感觉到这个filterChainProxy的存在了.通过配置中的"/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor"一句我们告诉filterChainProxy当Request来时,都有哪些Filter处理这个Request.
?? ?Step3/Step4: filterChainProxy调用filterChain中的第一个Filter,也就是httpSessionContextIntegrationFilter. 这个httpSessionContextIntegrationFilter是HttpSessionContextIntegrationFilter类的实例, 这个类正是"七剑"之一. 从它的名字上,我们也隐隐约约地感觉到了点什么: 把Context integrate 到HttpSession中? 对的, 在HttpSessionContextIntegrationFilter的doFilter方法里Acegi从HttpSession中获得SecurityContext对象(或没有的话新建个), 随后再把这个SecurityContext存放到SecurityContextHolder中, 很自然嘛,SecurityContextHolder就是用来放SecurityContext的. 做了这些处理后, httpSessionContextIntegrationFilter通过chain.doFilter方法将执行权交给下一filter.

??? 我们例子中下一个filter就是authenticationProcessingFilter,它是AuthenticationProcessingFilter的实例,看它名字里有Authentication跟"七剑"中的Authentication有关系? 不错, authenticationProcessingFilter类中有一个requiresAuthentication方法, 顾名思义,它是看当前的Request是否是用来做验证的,也就是说是否是登录的. 这就用到了Bean配置authenticationProcessingFilter里属性, 看Acegi的源码可以得到验证. 接下来, 在方法attemptAuthentication中Acegi从Request中取出username和password组建一个Authentication对象, 再由配置中的authenticationManager来加以验证,若"暗号"没对上的话, 就有一个AuthenticationException异常抛出, authenticationProcessingFilter catch住这个AuthenticationException,再通过sendRedirect方法在浏览器中指向authenticationFailureUrl的值"/login.jsp?login_error=1". 若"暗号"对上了,将通过方法successfulAuthentication重定向到defaultTargetUrl指定的页面, 同时Acegi把对上"暗号"的Authentication对象通过方法SecurityContextHolder.getContext().setAuthentication存放到SecurityContext中,以备后用.

?? ?Step5/Step6: Acegi将Request(当然还有Response)交给下一个Fillter, 我们例子中是filterInvocationInterceptor(实际上交给了exceptionTranslationFilter,这里我们为了讨论的方便,假定交给了filterInvocationInterceptor),这个filter再从SecurityContextHolder中取出SecurityContext,再取出里面的已经对上"暗号"的Authentication对象(此对象在本例中实际上是封装了users.properties里这样的"james=tom@1231,ROLE_TECHNICIAN"键值对), 再把这个Authentication对象交给当前bean中配置的accessDecisionManager属性以决定Authentication是否能访问它想访问的资源.经accessDecisionManager"研究"后发现可以访问,此时Acegi即将Request/Response交给我们系统里配置的相应方法(如Struts里配置的某一method).若"研究"时发现没权限,则以异常的方式交给上面提到的exceptionTranslationFilter,这个filter再重定向到loginFormUrl指定的URL上.

?? ?到这步骤已走完了, 那怎么没看到"七剑"中的另三剑呢? 它们是UsUserDetails对象里方法返回的GrantedAuthority[]一一比较, 若在比较过程中发现有个对应上了, 就表示有权访问,否则即无权. 这里所论述的过程正是上面accessDecisionManager所做的"研究".

?? ??好了,至此, 我们通过跟踪请求的来龙去脉把applicationContext-acegi-security.xml配置中的Filter走了一遍,更重要的是走filter时,我们与Acegi江湖里的鼎鼎大名的"七剑"有了短暂但美好的接触.

Acegi源码研究(五):七剑上天山

?

热点排行