Acegi 设计概述

来源:百度文库 编辑:神马文学网 时间:2024/04/29 05:34:12

Acegi 设计概述

作者: cac,作者保留版权,转载请注明出处。

第一步,认证(authentication)。Acegi调用AuthenticationManager(认证管理器)来对当前请求登陆系统用户进行验证,AuthenticationManager负责委托一个或多个Provider(认证提供者),并逐一遍历每个Provider,直到某一个Provider能够成功的验证用户的身份。Provider成功验证用户身份后,会返回一个Authentication(证明),Authentication中包括Principal(用户名),Credentials(通常是密码),Authorities(该用户所拥有的权限)。这样就完成了身份验证的步骤。

第二步,授权(authorization)。当Acegi获得Authentication后,也就确定了用户的身份。每当用户请求访问某受保护资源时,Acegi会调用AccessDecisionManager(访问决策管理器)来决定用户的Authentication是否有恰当的权限来访问当前访问的受保护资源,有则授权用户通过,无则抛出错误信息,以达到访问控制的目的。

 2. 安全保护方式

  • 保护Web应用程序
    当去保护Web应用程序时,Acegi使用Servlet Filter来拦截Servlet请求,并将这些请求转给AuthenticationManager,AccessDecisionManager或其他管理器来处理。
    Acegi提供了多个各种功能的Filter, 这些Filter按照先后顺序组成了一个 Filter Chain。当一个请求被提交道一个由Acegi所保护的Web应用程序时,该请求会按照如下顺序逐一通过Filter Chain:
     
    第一步, 请求通过ChannelProcessingFilter(通道处理过滤器,可选)。该过滤器负责检查当前请求的Channel,并判断是否已满足安全需 要。如果不满足,则由非安全的通道传输(Http)重定向于安全的通道传输(Https),以确保服务器与浏览器之间传输的数据加密。
     
    第二步,请求通过 AuthenticationProcessingFilter(认证处理过滤器)。该过滤器会判断该请求是否是一个认证请求(通常是 "/j_acegi_security_check")。如果是,则它会从请求中获取用户名和密码,并转交给AuthenticationManager 来认证用户身份。如果不是,则会直接转到下一个Filter。
     
    第三步,请求通过HttpSessionContextIntegrationFilter(HttpSession安 全上下文信息集成过滤器)。该过滤器负责将Authentication对象保存在HttpSession中,使其在下一个请求到来时仍可被获取。故 Authentication能跨越多个请求。
     
    第四步,请求通过FilterSecurityInterceptor(过滤器安全拦截器)。该过滤器会首先调用 AuthenticationManager判断用户是否已登陆认证,如还没认证成功,则重定向到登陆界面。认证成功,则并从 Authentication中获取用户的权限。然后从objectDefinitionSource属性获取各种URL资源所对应的权限。最后调用 AccessDecisionManager来判断用户所拥有的权限与当前受保华的URL资源所对应的权限是否相匹配。如果匹配失败,则返回403错误 (禁止访问)给用户。匹配成功则用户可以访问受保护的URL资源。
  •  保护方法调用
    当去保护方法调用时,Acegi使用Spring AOP,将"切面"应用于所代理的对象,以确保用户只有在拥有恰当授权时才可以调用受保护的方法。
    MethodSecurityInterceptor(方法调用安全拦截器)同样也是在调用方法之前,先调用AuthenticationManager 判断用户身份是否已验证,然后从objectDefinitionSource中获取方法所对应的权限,再调用 AccessDecisionManager来匹配用户权限和方法对应的权限。如果用户没有足够权限调用当前方法,则抛出 AccessDeniedException使方法不能被调用。

 3.过滤器链代理

Acegi的FilterChainProxy提供了一种很好的方式,使你不需要在web.xml配置Filters,而在Spring配置文件中加入, 从而能充分利用Spring IOC的优势。

FilterChainProxy其实也只是一个扩展后的Filter,它负责委托Spring中的各个实现了javax.servlet.Filter接口的Bean来执行过滤功能。如httpSessionContextIntegrationFilter, authenticationProcessingFilter,filterInvocationInterceptor等。

在web.xml中的配置FilterToBeanProxy:

<filter>
        <filter-name>Acegi Filter Chain Proxyfilter-name>|
        <filter-class>org.acegisecurity.util.FilterToBeanProxyfilter-class>
        <init-param>
                <param-name>targetClassparam-name>
                <param-value>org.acegisecurity.util.FilterChainProxyparam-value>
        init-param>
filter>
<filter-mapping>
        <filter-name>Acegi Filter Chain Proxyfilter-name>
        <url-pattern>/*url-pattern>
filter-mapping>

在Spring配置文件中相应的FilterChainProxy Bean:

<bean id="filterChainProxy"   class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
                <value>
                        CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                        PATTERN_TYPE_APACHE_ANT
                         /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
                value>
        property>
bean>

4. Acegi Exceptions 管理机制

Acegi的异常管理机制做得不错,基本上可以满足权限管理需求。在其结构基础上继承实现自己的异常类也是很方便的。

所有Acegi的异常都是在 AcegiSecurityException 上继承而来的,其中最主要的是 AuthenticationException 和 AccessDeniedException。

这里需要注意的是 AcegiSecurityException 继承了Spring的 NestedRuntimeException,而NestedRuntimeException又是继承RuntimeException的。
所以抛出的时候不需要throws, 而捕捉的时候需要专门catch RuntimeException。

AuthenticationException 是所有授权相关的异常的父类,当用户身份验证失败时就会抛出这个异常。

AccessDeniedException 是所有认证相关的异常的父类,当资源被拒绝访问时就会抛出这个异常。

在Acegi 中,通过ExceptionTranslationFilter(异常转换过滤器)来对各种异常进行捕获和处理,并重定向到不同的错误信息显示页面。

如遇到AuthenticationException 就会重定向到登陆页面,遇到AccessDeniedException就会无权访问资源页面。你还可以继承ExceptionTranslationFilter基础上覆盖handleException方法来实现你自己的系统中异常的处理。

<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
                <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
        <property name="loginFormUrl" value="/login.jsp" />
        <property name="forceHttps" value="false" />
                bean>
        property>
        <property name="accessDeniedHandler">
                <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
        <property name="errorPage" value="/accessDenied.jsp" />
                bean>
        property>
bean>