Acegi Security(Acegi)简介及入门

概述 
    对于任何一个完整的应用系 统,完善的认证和授权机制是必不可少的。Acegi Security(以下简称Acegi)是一个能为基于Spring的企业应用提供强大而灵活安全访问控制解决方案的框架,Acegi已经成为 Spring官方的一个子项目,所以也称为Spring Security。它通过在Spring容器中配置一组Bean,充分利用Spring的IoC和AOP功能,提供声明式安全访问控制的功能。虽然,现在 Acegi也可以应用到非Spring的应用程序中,但在Spring中使用Acegi是最自然的方式。 
Acegi可以实现业务对象方法级的安 全访问控制粒度,它提供了以下三方面的应用程序的安全: 

? URL资源的访问控制 
    如所有用户(包括其名用户)可以访问index.jsp登录页面,而只有授权的用户可以访问/user/addUser.jsp页面。Acegi允许通过 正则表达式或Ant风格的路径表达式定义URL模式,让授权用户访问某一URL匹配模式下的对应URL资源。 

业务 类方法的访问控制 
    Spring容器中所有Bean的方法都可以被Acegi管理,如所有用户可以调用BbtForum#getRefinedTopicCount()方 法,而只有授权用户可以调用BbtForum#addTopic()方法。 

? 领域对象的访问控制 
    业务类方法代表一个具体的业务操作,比如更改、删除、审批等,业务类方法访问控制解决了用户是否有调用某种操作的权限,但并未对操作的客体(领域对象)进 行控制。对于我们的论坛应用来说,用户可以调用BbtForum#updateUser(User user)方法更改用户注册信息,但应该仅限于更改自己的用户信息,也即调用BbtForum#updateUser()所操作的User这个领域对象必 须是受限的。 

    Acegi通过多个不同用途的Servlet过滤器对URL资源进行保护,在请求受保护的URL资源前,Acegi的Servlet过滤器判断用户是否有 权访问目标资源,授权者被开放访问,而未未被授权者将被阻挡在大门之外。 
    Acegi通过Spring AOP对容器中Bean的受控方法进行拦截,当用户的请求引发调用Bean的受控方法时,Acegi的方法拦截器开始工作,阻止未授权者的调用。 
    
    对领域对象的访问控制建立在对Bean方法保护的基础上,在最终开放目标Bean方法的执行前,Acegi将检查用户的ACL(Aeccess Control List:访问控制列表)是否包含正要进行操作的领域对象,只有领域对象被授权时,用户才可以使用Bean方法对领域对象进行处理。此外,Acegi还可 以对Bean方法返回的结果进行过滤,将一些不在当前用户访问权限范围内的领域对象剔除掉——即传统的数据可视域范围的控制。一般来说,使用Acegi控 制数据可视域未非理想的选择,相反通过传统的动态SQL的解决方案往往更加简单易行。 

    从本质特性上来说,Servlet过滤器就是最原始的原生态AOP,所以我们可以说Acegi不但对业务类方法、领域对象访问控制采用了AOP技术方案, 对URL资源的访问控制也使用了AOP的技术方案。使用AOP技术方案的框架是令人振奋的,这意味着,开发者可以在应用程序业务功能开发完毕后,轻松地通 过Acegi给应用程序穿上安全保护的“铁布衫”。

    Acegi体系结构 
    乘飞机前需要通过安检,乘客必须提供身份证以验证其身份。在通过安检进入候机室后,国航、海航、南航等不同航空公司的飞机陆续到达,但你只能登上机票上对 应航班的飞机。在登机后,只能坐在机票对应的座位上——你不能抢占他人的座位,你不能在座位上刻字留念、你不能要求空姐打开机窗…… 

    乘飞机的过程最能体现安全控制的流程,我们可以从中找到身份认证、资源访问控制、领域对象安全控制的对应物:安检对应身份认证,登机对应资源访问控制而按 号就座则对应领域对象安全控制。 
    Acegi通过两个组件对象完成以上安全问题的处理:AuthenticationManager(认证管理器)、 AccessDecisionManager(访问控制管理器),如图 1所示:


图 1 Acegi体系结构

    SecurityContextHolder是框架级的容器,它保存着和所有用户关联SecurityContext实 例,SecurityContext承载着用户(也称认证主体)的身份信息的权限信息, AuthenticationManager、AccessDecisionManager将据此进行安全访问控制。 
    
    SecurityContext的认证主体安全信息在一个HTTP请求线程的多个调用之间是共享的(通过ThreadLocal),但它不能在多个请求之 间保持共享。为了解决这个问题,Acegi将认证主体安全信息缓存于HttpSession中,当用户请求一个受限的资源时,Acegi通过 HttpSessionContextIntegrationFilter将认证主体信息从HttpSession中加载到 SecurityContext实例中,认证主体关联的SecurityContext实例保存在Acegi容器级的 SecurityContextHolder里。当请求结束之后,HttpSessionContextIntegrationFilter执行相反的操 作,将SecurityContext中的认证主体安全信息重新转存到HttpSession中,然后从SecurityContextHolder中清 除对应的SecurityContext实例。通过HttpSession转存机制,用户的安全信息就可以在多个HTTP请求间共享,同时保证 SecurityContextHolder中仅保存当前有用的用户安全信息,其整体过程如图 2所示:


图 2 SecurityContext在HttpSession和请求线程间的转交过程


    当用户请求一个受限的资源时,AuthenticationManager首先开始工作,它象一个安检入口,对用户身份进行核查,用户必须提供身份认证的 凭证(一般是用户名/密码)。在进行身份认证时,AuthenticationManager将身份认证的工作委托给多个 AuthenticationProvider。因为在具体的系统中,用户身份可能存储在不同的用户信息安全系统中(如数据库、CA中心、LDAP服务 器),不同用户信息安全系统需要不同的AuthenticationProvider执行诸如用户信息查询、用户身份判断、用户授权信息获取等工作。只要 有一个AuthenticationProvider可以识别用户的身份,AuthenticationManager就通过用户身份认证,并将用户的授 权信息放入到SecurityContext中。 

   当用户通过身份认证后,试图访问某个受限的程序资源时,AccessDecisionManager开始工作。 AccessDecisionManager采用民主决策机制判断用户是否有权访问目标程序资源,它包含了多个AccessDecisionVoter。 在访问决策时每个AccessDecisionVoter都拥有投票权,AccessDecisionManager统计投票结果,并按照某种决策方式根 据这些投票结果决定最终是否向用户开放受限资源的访问。

    重要组件类介绍 
    每个框架都有一些核心的概念,这些概念被固化为类和接口,成为框架的重要组件类。框架的管理类、操作类都在这些组件类的基础上进行操作。在进入Acegi 框架的具体学习前,有必要事先了解一下这些承载Acegi框架重要概念的组件类。 
    首先,我们要接触是UserDetails接口,它代表一个应用系统的用户,该接口定义了用户安全相关的信息,如用户名/密码,用户是否有效等信息,你可 以根据以下接口方法进行相关信息的获取: 
    String getUsername():获取用户名; 
     String getPassword():获取密码; 
     boolean isAccountNonExpired():用户帐号是否过期; 
     boolean isAccountNonLocked():用户帐号是否锁定; 
     boolean isCredentialsNonExpired():用户的凭证是否过期; 
     boolean isEnabled():用户是否处于激活状态。 
    当以上任何一个判断用户状态的方法都返回false时,用户凭证就被视为无效。 
    UserDetails还定义了获取用户权限信息的方法:GrantedAuthority[] getAuthorities(),GrantedAuthority代表用户权限信息,它定义了一个获取权限描述信息(以字符串表示,如 PRIV_COMMON)的方法:String getAuthority()。


图 3 用户和权限

    在未使用Acegi之前,我们可能通过类似User、Customer等领域对象表示用户的概念,并在程序中编写相应的用户认证的逻辑。现在,你要做的一 个调整是让原先这些代表用户概念的领域类实现UserDetails接口,这样,Acegi就可以通过UserDetails接口访问到用户的信息了。 

    UserDetails可能从数据库、LDAP等用户信息资源中返回,这要求有一种机制来完成这项工作,UserDetailsService正是充当这 一角色的接口。UserDetailsService接口很简单,仅有一个方法:UserDetails loadUserByUsername(String username) ,这个方法通过用户名获取整个UserDetails对象。 
Authentication 代表一个和应用程序交互的待认证用户,Acegi从类似于登录页面、Cookie等处获取待认证的用户信息(一般是用户名密码)自动构造 Authentication实例。


图 4 Acegi的认证用户

    Authentication可以通过Object getPrincipal()获取一个代表用户的对象,这个对象一般可以转换为UserDetails,从中可以取得用户名/密码等信息。在 Authentication被AuthenticationManager认证之前,没有任何权限的信息。在通过认证之后,Acegi通过 UserDetails将用户对应的权限信息加载到Authentication中。Authentication拥有一个 GrantedAuthority[] getAuthorities()方法,通过该方法可以得到用户对应的权限信息。 
    Authentication和UserDetails很容易被混淆,因为两者都有用户名/密码及权限的信息,接口方法也很类似。其实 Authentication是Acegi进行安全访问控制真正使用的用户安全信息的对象,它拥有两个状态:未认证和已认证。UserDetails是代 表一个从用户安全信息源(数据库、LDAP服务器、CA中心)返回的真正用户,Acegi需要将未认证的Authentication和代表真实用户的 UserDetails进行匹配比较,通过匹配比较(简单的情况下是用户名/密码是否一致)后,Acegi将UserDetails中的其它安全信息(如 权限、ACL等)拷贝到Authentication中。这样,Acegi安全控制组件在后续的安全访问控制中只和Authentication进行交 互。

    由于Acegi对程序资源进行访问安全控制时,一定要事先获取和请求用户对应的Authentication,Acegi框架必须为 Authentication提供一个“寓所”,以便在需要时直接从“寓所”把它请出来,作为各种安全管理器决策的依据。 

    SecurityContextHolder就是Authentication容身的“寓所”,你可以通过 SecurityContextHolder.getContext().getAuthenication()代码获取Authentication。 细心观察一下这句代码,你会发现在SecurityContextHolder和Authentication之间存在一个getContext()中 介,这个方法返回SecurityContext对象。SecurityContext这个半路杀出来的程咬金有什么特殊的用途呢?我们知道 Authentication是用户安全相关的信息,请求线程其它信息(如登录验证码等)则放置在SecurityContext中,构成了一个完整的安 全信息上下文。SecurityContext接口提供了获取和设置Authentication的方法: 
 Authentication getAuthentication() 
 void setAuthentication(Authentication authentication)


图 5 认证用户信息存储器

    SecurityContextHolder是Acegi框架级的对象,它在内部通过ThreadLocal为请求线程提供线程绑定的 SecurityContext对象。这样,任何参与当前请求线程的Acegi安全管理组件、业务服务对象等都可以直接通过 SecurityContextHolder.getContext()获取线程绑定的SecurityContext,避免通过方法入参的方式获取用户 相关的SecurityContext。 

    线程绑定模式对于大多数应用来说是适合的,但是应用本身会创建其它的线程,那么只有主线程可以获得线程绑定SecurityContext,而主线程衍生 出的新线程则无法得到线程绑定的SecurityContext。Acegi考虑到了这些不同应用情况,提供了三种绑定SecurityContext的 模式: 
 SecurityContextHolder.MODE_THREADLOCAL:SecurityContext绑定到主线程,这是默认的模式; 
 SecurityContextHolder.MODE_GLOBAL:SecurityContext绑定到JVM中,所有线程都使用同一个 SecurityContext; 
 SecurityContextHolder.MODE_INHERITABLETHREADLOCAL::SecurityContext绑定到主线程 及由主线程衍生的线程中。 
    你可以通过SecurityContextHolder.setStrategyName(String strategyName)方法指定SecurityContext的绑定模式。

    用户认证过程 
Acegi支持多种方式的用户认证:如典型的基于数据库的认证、基于LDAP的认 证、基于Yale中心认证等方式。不同的认证环境拥有不同的用户认证方式,现在我们先抛开这些具体的细节,考察一下Acegi对受限资源进行访问控制的典 型过程: 
    1.你点击一个链接访问一个网页; 
    2.浏览器发送一个请求到服务器,服务器判断出你正在访问一个受保护的资源; 
    3.如果此时你并未通过身份认证,服务器发回一个响应提示你进行认证——这个响应可能是一个HTTP响应代码,抑或重定向到一个指定页面; 
    4.根据系统使用认证机制的不同,浏览器或者重定向到一个登录页面中,或者由浏览器通过一些其它的方式获取你的身份信息(如通过BASIC认证对话框、一 个Cookie或一个X509证书); 
    5.浏览器再次将用户身份信息发送到服务器上(可能是一个用户登录表单的HTTP POST信息、也可能是包含认证信息的HTTP报文头); 
    6.服务器判断用户认证信息是否有效,如果无效,一般情况下,浏览器会要求你继续尝试,这意味着返回第3步。如果有效,则到达下一步; 
    7.服务器重新响应第2步所提交的原始请求,并判断该请求所访问的程序资源是否在你的权限范围内,如果你有权访问,请求将得到正确的执行并返回结果。否 则,你将收到一个HTTP 403错误,这意味着你被禁止访问。 
    在Acegi框架里,你可以找到对应以上大多数步骤的类,其中ExceptionTranslationFilter、 AuthenticationEntryPoint、AuthenticationProvider以及Acegi的认证机制是其中的代表者。 

    ExceptionTranslationFilter是一个Acegi的Servlet过滤器,它负责探测抛出的安全异常。当一个未认证用户访问服务器 时,Acegi将引发一个Java异常。Java异常本身对HTTP请求以及如何认证用户是一无所知 的,ExceptionTranslationFilter适时登场,对这个异常进行处理,启动用户认证的步骤(第3步)。如果已认证用户越权访问一个资 源,Acegi也将引发一个Java异常,ExceptionTranslationFilter则将这个异常转换为HTTP 403响应码(第7步)。可见,Acegi通过异常进行通讯,
ExceptionTranslationFilter接收这些异常并作出相应的动 作。 

    当ExceptionTranslationFilter通过Java异常发现用户还未认证时,它到底会将请求重定向哪个页面以要求用户提供认证信息呢? 这通过咨询AuthenticationEntryPoint来达到目的——Acegi通过AuthenticationEntryPoint描述登录页 面。 

    当你的浏览器通过HTTP表单或HTTP报文头向服务器提供用户认证信息时,Acegi需要将这些信息收集到Authentication中,Acegi 用“认证机制”描述这一过程。此时,这个新生成Authentication只包含用户提供的认证信息,但并未通过认证。
AuthenticationProvider 负责对Authentication进行认证。AuthenticationProvider究竟如何完成这一过程呢?请回忆一下上节我们所介绍的 UserDetails和UserDetailsService,大多数AuthenticationProvider通过 UserDetailsService获取和未认证的Authentication对应的UserDetails并进行匹配比较来完成这一任务。当用户认 证信息匹配时,Authentication被认为是有效的,AuthenticationProvider进一步将UserDetails中权限、 ACL等信息拷贝到Authentication。 
当Acegi通过认证机制收集到用户认证信息并填充好Authentication 后,Authentication将被保存到SecurityContextHolder中并处理用户的原始请求(第7步)。 

    你完全可以抛开Acegi的安全机制,编写自己的Servlet过滤器,使用自己的方案构建Authentication对象并将其放置到 SecurityContextHolder中。也许你使用了CMA(Container 
Managed Authentication:容器管理认证),CMA允许你从ThreadLocal或JNDI中获取用户认证信息,这时你只要获取这些信息并将其转换 为Authentication就可以了。

    安全对象访问控制 
    Acegi称受保护的应用资源为“安全对象”,这包括URL资源和业务类方法。我们知道在Spring AOP中有前置增强、后置增强、异常增强和环绕增强,其中环绕增强的功能最为强大——它不但可以在目标方法被访问前拦截调用,还可以在调用返回前改变返回 的结果,甚至抛出异常。Acegi使用环绕增强对安全对象进行保护。 
    Acegi通过AbstractSecurityInterceptor为安全对象访问提供一致的工作模型,它按照以下流程进行工作: 
    1. 从SecurityContext中取出已经认证过的Authentication(包括权限信息); 
    2. 通过反射机制,根据目标安全对象和“配置属性”得到访问目标安全对象所需的权限; 
    3. AccessDecisionManager根据Authentication的授权信息和目标安全对象所需权限做出是否有权访问的判断。如果无权访 问,Acegi将抛出AccessDeniedException异常,否则到下一步; 
4. 访问安全对象并获取结果(返回值或HTTP响应); 
5. AbstractSecurityInterceptor可以在结果返回前进行处理:更改结果或抛出异常。     Acegi称受保护的应用资源为“安全对象”,这包括URL资源和业务类方法。我们知道在Spring AOP中有前置增强、后置增强、异常增强和环绕增强,其中环绕增强的功能最为强大——它不但可以在目标方法被访问前拦截调用,还可以在调用返回前改变返回 的结果,甚至抛出异常。Acegi使用环绕增强对安全对象进行保护。     Acegi通过AbstractSecurityInterceptor为安全对象访问提供一致的工作模型,它按照以下流程进行工作:     1. 从SecurityContext中取出已经认证过的Authentication(包括权限信息);     2. 通过反射机制,根据目标安全对象和“配置属性”得到访问目标安全对象所需的权限;     3. AccessDecisionManager根据Authentication的授权信息和目标安全对象所需权限做出是否有权访问的判断。如果无权访 问,Acegi将抛出AccessDeniedException异常,否则到下一步; 4. 访问安全对象并获取结果(返回值或HTTP响应); 5. AbstractSecurityInterceptor可以在结果返回前进行处理:更改结果或抛出异常。


图 6 AbstractSecurityInterceptor工作流程

    安全对象和一般对象的区别在于前者通过Acegi的“配置属性”进行了描述,如“/view.jsp=PRIV_COMMON”配置属性就将“ /view.jsp”这个URL资源标识为安全对象,它表示用户在访问/view.jsp时,必须拥有PRIV_COMMON这个权限。配置属性通过 XML配置文件,注解、数据库等方式提供。安全对象通过配置属性表示为一个权限,这样,Acegi就可以根据Authentication的权限信息获知 用户可以访问的哪些安全对象。 
    根据安全对象的性质以及具体实现技术,AbstractSecurityInterceptor拥有以下三个实现类: 
 FilterSecurityInterceptor:对URL资源的安全对象进行调用时,通过该拦截器实施环绕切面。该拦截器使用Servlet过滤器 实现AOP切面,它本身就是一个Servlet过滤器; 
 MethodSecurityInterceptor:当调用业务类方法的安全对象时,可通过该拦截器类实施环绕切面; 
 AspectJSecurityInterceptor:和MethodSecurityInterceptor类似,它是针对业务类方法的拦截器,只不 过它通过AspectJ实施AOP切面。

    Acegi版本升级的一些重大变化 
    Acegi项目开始于2003年,Acegi团队在发布新版本时非常谨慎,在本书写作之时,Acegi最新版本为1.0.3。在此之前Acegi已经发布 了10多个预览版本,由于Acegi框架优异的表现,许多大型应用早在Acegi 1.0正式版本发布之前(2006年5月),就已经采用Acegi框架作为其安全访问控制的解决方案。

    在Acegi社区里,来自世界各地众多优秀的安全领域专家对Acegi的改进和发展献计献策,Acegi团队广泛听取并吸收各种有益的建议,将它们融入到 Acegi的框架中,使Acegi成为构建在Spring基础上企业应用的首选安全控制框架。 
Acegi 1.0.3版本相比于早期预览版本发生了很大的变化,对于需要进行Acegi版本的项目来说,了解这一变化特别重要。下面,我们列出Acegi的一些重大 的升级更新: 
 包名的更新:在0.9.0及之前的版本中,Acegi采用net.sf.acegisecurity包名前缀,在1.0.0版本之后更改为 org.acegisecurity(Hibernate也走过相同的道路,好在Acegi在正式版本发布之时就完成了这种转变); 

 ACL模块的调整:ACL模块发生了重大的调整,Acegi团队接收了社区大量关于ACL模块的反馈意见,重新设计了ACL模块的底层结构,在性能、封装 性、灵活性上得到了质的提升。事实上,Acegi使用org.acegisecurity.acls包代替了原来的 org.acegisecurity.acl包,后者将在后期的版本中删除,由于这种伤筋动骨的变化,将很难兼容原来ACL模块。不过,目前基于新框架的 ACL模块还没有进行充分的测试,Acegi承诺在1.1.0版本发布时提供最终的实现; 

 删除了ContextHolder及其相关类:在Acegi 0.9版本中,ContextHolder及其相关类被彻底从Acegi项目中删除。ContextHolder可以在多个HTTP请求中共享同一个 ThreadLocal,这和Spring提倡的ThreadLocal只应在同一线程中共享相悖。现在,Acegi使用 SecurityContextHolder替换ContextHolder,它的生命周期是一个HTTP 请求; 

 使用FilterChainProxy同时代理多个过滤器:在早期的版本中,Acegi通过FilterToBeanProxy将web.xml中的 Servlet过滤器定义转移到Spring容器中。这比直接在web.xml中配置Servlet过滤器要方便一些,但是Acegi框架往往需要定义多 个Servlet过滤器,使web.xml配置文件变得冗长难看。在Acegi 0.8版本中提供FilterChainProxy,它可以同时代理多个Servlet过滤器并保证过滤器的顺序。因此在新版本 中,FilterChainProxy成为推荐的选择。 

    小结 
    Acegi是Spring项目下一个成熟的安全访问控制框架,它允许利用了Spring IoC的AOP的功能完成安全对象的访问控制。在Acegi框架中,SecurityContextHolder处于非常核心的位置,它是存放认证管理器 用户安全信息SecurityContext的“容器”,SecurityContext保存着用户安全访问控制所需的信息,直接被访问决策管理器使用。 HttpSessionContextIntegrationFilter通过在SecurityContextHolder和HttpSession中 摆渡SecurityContext,使多个请求线程可以共享同一个SecurityContext。


一、Acegi Security  介绍

 

    1、为基于J2EE企业应用提供了全面安全服务 

l将系统的安全逻辑从业务中分离出来
l提供很多认证授权策略
l基于URLWEB资源访问控制
l业务方法调用访问控制
l领域对象访问控制  Access Control ListACL
l单点登录(Central Authentication Service 缓存、信道安全(Channel Security)管理等功能
2、Acegi发展历史
2003年初——Spring本身作为一个sourceforge的项目出现。

2003年年底——acegi开始,当时叫springacegi安全系统

20065—— acegi 1.0.0最终版本发布。

2007年年底——成为spring组合项目,更名Spring Security

20097——Spring Security 3.0已经发布

2010年7月——Spring Security 3.1已经发 

3、安全原理

 

 安全包括认证授权两个主要操作。

认证是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在你系统中执行行动的其他系统。

授权指的一个用户能否在你的应用中执行某个操作。在到达授权判断之前,身份的主体已经由身份验证过程建立了。

 这些概念是通用的,不是Spring Security特有的。

  

Spring Acegi拥有丰富灵活的认证模型,列举几个认证技术:

 

HTTP BASIC authentication headers (一个基于IEFT RFC的标准)

 

LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境)

 

JA-SIG Central Authentication Service (也被称为CAS,这是一      个流行的开源单点登录系统)

 

Java Authentication and Authorization Service (JAAS)

 

Form-based authentication (提供简单用户接口的需求)

 

Spring Acegi在授权方面主要有三个领域

 

 

l授权web请求
 
l授权被调用方法
 
l授权访问单个对象的实例
 
 
二 、Acegi Security  原理
 
1、 乘飞机的安全问题
 

乘飞机前需要通过安检,乘客必须提供身份证以验证其身份。在通过安检进入候机室后,国航、海航、南航等不同航空公司的飞机陆续到达,但你只能登上机票上对应航班的飞机。在登机后,只能坐在机票对应的座位上——你不能抢占他人的座位,你不能在座位上刻字留念、你不能要求空姐打开机窗……

  乘飞机的过程体现安全控制的流程:

 

 

安检--身份认证

 

 

登机--资源访问控制

 

 

按号就座领域对象安全控制

 

2、Acegi架构

 

 

Acegi通过两个组件对象完成安全问题的处理:

 

AuthenticationManager(认证管理器)

 

AccessDecisionManager(访问控制管理器或者叫授权管理器)

 

 

Acegi框架中,SecurityContextHolder处于非常核心的位置,它是存放认证管理器用户安全信息SecurityContext容器SecurityContext保存着用户安全访问控制所需的信息,直接被访问决策管理器使用。

    HttpSessionContextIntegrationFilter通过在SecurityContextHolderHttpSession中摆渡SecurityContext,使多个请求线程可以共享同一SecurityContext

 

3、Acegi 实现以filter为中心

 

 

 

   

 

 

 用户认证过程

 

Acegi支持多种方式的用户认证:如典型的基于数据库的认证、基于LDAP的认证等。先抛开细节,看一下Acegi对受限资源进行访问控制的典型过程:

1.你点击一个链接访问一个网页;

2.浏览器发送一个请求到服务器,服务器判断出你正在访问一个受保护的资源;

3.如果此时你并未通过身份认证,服务器发回一个响应提示你进行认证——这个响应可能是一个HTTP响应代码,抑或重定向到一个指定页面;

4.根据系统使用认证机制的不同,浏览器或者重定向到一个登录页面中,或者由浏览器通过一些其它的方式获取你的身份信息(如通过BASIC认证对话框、一个Cookie);

5.浏览器再次将用户身份信息发送到服务器上(可能是一个用户登录表单的HTTP POST信息、也可能是包含认证信息的HTTP报文头);

6.服务器判断用户认证信息是否有效,如果无效,一般情况下,浏览器会要求你继续尝试,这意味着返回第3步。如果有效,则到达下一步;

7.服务器重新响应第2步所提交的原始请求,并判断该请求所访问的程序资源是否在你的权限范围内,如果你有权访问,请求将得到正确的执行并返回结果。否则,你将收到一个HTTP 403错误,这意味着你被禁止访问。

 

 授权过程

Acegi称受保护的应用资源为安全对象,这包括URL资源和业务类方法。spring AOP中有前置advice(处理、拦截器、通知)、后置advice 、异常advice和环绕advice 。Acegi使用环绕advice对安全对象进行保护。 AcegiAbstractSecurityInterceptor为安全对象访问提供一致的工作模型,它按照以下流程进行工作:

 

1. 从SecurityContext中取出已经认证过的Authentication(包括权限信息);

2. 通过反射机制,根据目标安全对象和配置属性得到访问目标安全对象所需的权限;

3. AccessDecisionManager根据Authentication的授权信息和目标安全对象所需权限做出是否有权访问的判断。如果无权访问,Acegi将抛出AccessDeniedException异常,否则到下一步;

4. 访问安全对象并获取结果(返回值或HTTP响应);

5. AbstractSecurityInterceptor可以在结果返回前进行处理:更改结果或抛出异常。

 

 

三、Acegi Security配置

 

1、基本环境配置

 

第一步确保jar文件放到正确的位置(/WEB-INF/lib/

acegi-security-1.0.1.jar
aopalliance-1.0.jar
spring-2.0.2.jar
等相关jar
第二步,web.xml文件里配置一个FilterToBeanProxy

<filter>

    <filter-name>securityFilter</filter-name>

    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>

    <init-param>

      <param-name>targetBean</param-name>

      <param-value>filterChainProxy</param-value>

    </init-param>

  </filter>

 

  <filter-mapping>

    <filter-name>securityFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

 

第三步applicationContext-security.xml文件的配置

 <bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy">

        <property name="filterInvocationDefinitionSource">

            <value>

                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

                PATTERN_TYPE_APACHE_ANT               /**=httpSessionContextIntegrationFilter,userPreferencesFilter,authenticationProcessingFilter </value>

        </property>

    </bean>

2、登录验证

 

 

 

 

 

3、方法保护

 

 

 

4、Domain Object安全(ACL

 

 

ACL用来做细粒度权限控制所用的一种权限模型。具体到每一条数据的权限。保障Domain Object安全。

 

 ACL最简单的描述——两个业务员每个人只能查看操作自己签的合同,而不能看到对方的合同信息。

 

 最典型的ACL实现——操作系统(window, unix)的文件访问控制系统,精确定义了某个用户或角色对某个特定文件的读、写、执行等权限。

 

 

l ACL_READ 指的是这个 Voter 对哪些 SecurityConfig 起作用。可以把 ACL_READ 配置在想要拦截的 Method 上。比方说要拦截 readOrder 这个方法,以实现 ACL 控制,可以这样配置 orderManager.readOrder =ACL_READ
lprocessDomainObjectClass指出哪些DomainObject是要进行ACL校验的。
laclManager主要负责在权限列表根据用户和DomainObject取得acl列表。
lrequirePermission指出要进行这个操作必须具备的acl权限,比方说read操作就必须有ADMINISTRATIONREAD两个权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值