spring 第十章 Acegi安全框架

 第10章 Acegi安全框架
安全保护机制三步曲:认证管理器,决策管理器,过滤器链
认证和授权
一基于角色的权限控制 (Role Based Access Control RBAC)
  授权-角色-用户
Java验证和授权服务(Java Authentication and Authorization Service,JAAS)是标准的谁和授权服务
二Acegi安全框架
1.Authentication对象封装了Principal(主体,通常是用户信息)和Credentials(凭证,通常中口令).
  Acegi使用SecurityContext(代替HttpSession,是ThreadLocal..)来存储Authentication.(方法SecurityContextHolder.getContext.getAuthentication() )
2.有了Authentication,再通过下几个组件 ,来确保被访问资源的安全
                            3 安全拦截器(FilterChain,过滤器链)


认证管理器 1         决策管理器   2        运行管理器        
(AuthenticationManager  (AccessDecisionManager,决定是否有权限)
 验证身份)
3详细讲解
 3.1AuthencationManager认证管理器,该组件的任务就是对用户进行认证。认证管理器通过识别
Principal和Credentials来确定用户的身份。
Acegi提供了一个默认的Authentication的实现类ProviderManager.
ProviderManager并不直接去验证用户提供的Principal和Credentials,而是将它们委托给一个或多个AuthenticationProvider来验证,ProviderManager将逐一遍历每个AuthenticationProvider,
只要有一个Authentication Provider成功地认证了用户有,该认证过程就结束。
eg.
   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="daoAuthenticationProvider" />
                <ref bean="rememberMeAuthenticationProvider" />
            </list>
        </property>
    </bean>
 <!-- 基于DAO验证的AuthenticationProvider -->
    <bean id="daoAuthenticationProvider"
        class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <bean id="rememberMeAuthenticationProvider"
        class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
        <property name="key" value="remember_Me" />
    </bean>

<!-- 使用内存DAO,实际应用时可用JdbcDao代替?? -->
    <bean id="userDetailsService"
        class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
        <property name="userMap">
            <value>
                admin=password,enabled,ROLE_ADMIN,ROLE_USER  //格式“用户名=口令,<账户是否有效>,<角色1>,<角色2>”
                test=test,enabled,ROLE_USER
                guest=guest,disabled,ROLE_USER
            </value>
        </property>
    </bean>
Acegi已经提供了多个Authentication Provider可供选择:
  AuthByAdapterProvider: 通过Web容器来验证用户身份。
  CasAuthenticationProvider:通过CAS服务来验证用户身份,是基于单点登陆的认证方式。
 DaoAuthenticationProvider:通过数据库存储的用户名口令信息来验证用户身份,这是Web应用程序最常见的认证方式
 JassAuthenticationProvider:通过JAAS服务来验证用户身份。
 PasswordDaoAuthenticationProvider:通过数据库认证,但是具体过程由底层数据源完成
 RememberMeAuthenticationProvider:通过浏览器提供的Cookie来验证用户上次是否已经成功登陆并在有效期内,
若Cookie被接受,则通过认证。
 RemoteAuthenticationProvider:通过远程服务验证用户身份.

3.2AccessDecisionManager(决策管理器)
   <bean id="accessDecisionManager"
        class="org.acegisecurity.vote.AffirmativeBased">   //AffirmativeBased,ConsensusBased,UnamouseBased三种值
        <property name="decisionVoters">                      //每个投票者(RoleVoter)可以以3种方式进行投票:
//ACCESS_GRANTED赞/成票,ACCESS_DENIED拒绝票,ACCESS_ABSTAIN弃权票
            <list>
                <bean class="org.acegisecurity.vote.RoleVoter" />
            </list>
        </property>
        <property name="allowIfAllAbstainDecisions" value="false" />  //allowIfAllAbstainDecisions
    </bean>

AffirmativeBased:至少有一个投票者允许访问该资源,这是最常见的方式。
ConsensusBased:所有投票者都允许访问时,才允许访问该资源,这是最严格的方式。
UnamouseBased:如果没有投票者拒绝访问,就允许访问该资源。
这3个accessDecisionManager有一个共同的allowIfAllAbstainDecisions属性,设为true,表示如果所有的投票者都
弃权,也可以允许访问。 为flase,则都弃权,也不可以访问。
 
3.3FilterChain
Acegi已经提供了一系列非常有用的Filter.
1ChannelProcessingFilter:确保当前URL以指定的协议访问,例如,必须对以/secure/开头的URL使用HTTPS访问。
2ConcurrentSessionFilter:阻止同一用户在某一段时间内多次登陆。
3HttpSessionContextIntegrationFilter:由于用户的认证信息存放在Http Session 中,这个过滤器的作用就是从Session
中获得用户的认证信息,然后将其关联到当前请求中,如果没有这个过滤器,后续的请求处理就无法获得已认证的用户的身份信息。
4LogoutFilter:通过过滤特定的URL(例如/j_logout),LogoutFilter可以实现用户注销的功能。
5AuthenticationProcessingFilter:通过过滤特定的URL(例如,/j_security_check)),AuthenticationProcessingFilter可以
 验证用户朐和口令,实现用户登陆的功能。   Acegi提供了多种登录的方式,除了由应用程序自身通过JDBC验证外,
还有CasProcessingFilter,JbossIntegrationFilter等。
6SecurityContextHolderAwareRequestFilter:如果应有用程序需要调用HttpServlet Request的getRemoteUser()获得用户
身份,就可以使用SecurityContextHolder Aware RequestFilter来包装原始的HttpServletRequest,它使用一个代理模式返回Acegi Authentication对象的Principal.
7 RememberMeProcessingFilter:实现雇用户登录信息的功能,使用户在一段时间内都不必输入用户名和口令,Acegi
默认采用Cookie记住用户登录信息。
8 AnonymouseProcessingFilter:如果当前用户没有登录,就将一个匿名用户身份放入SecurityContext中。
9 ExceptionTranslationFilter:捕获任何与Acegi安全相关的异常,然后根据需要将用户导向到登录页面,或者直接发送
一个403禁止访问的错误代码。
10 FilterSecurityInterceptor:最终真正保护Web资源的拦截器。

三实例
eg1.保护web资源,工程名:Spring_Acegi(通过Filter来对web页面进行保护,Filter有对URL过滤的功能,有些用户能访问/user目录,有些访问/admin目录)
知识点:Acegi有多个Filter,但我们却只需在web.xml中配置一个特殊的
Acegi Filter(FilterChainProxy)
 <!-- Acegi过滤器 -->
    <filter>
        <filter-name>acegiFilterChain</filter-name>
        <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
        <init-param>
            <param-name>targetClass</param-name>
            <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
        </init-param>
    </filter>
其他的Filter通过依赖注入的方式在Acegi的Spring xml中定义。(在security.xml中 过滤器链中链上...
<value>/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter,securityInterceptor </value>)


security.xml
<!--========================================================================
         认证管理器
    =========================================================================-->
    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="daoAuthenticationProvider" />
                <ref bean="rememberMeAuthenticationProvider" />
            </list>
        </property>
    </bean>

    <!-- 基于DAO验证的AuthenticationProvider -->
    <bean id="daoAuthenticationProvider"
        class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <bean id="rememberMeAuthenticationProvider"
        class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
        <property name="key" value="remember_Me" />
    </bean>

    <!-- 使用内存DAO,实际应用时可用JdbcDao代替 -->
    <bean id="userDetailsService"
        class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
        <property name="userMap">
            <value>
                admin=password,enabled,ROLE_ADMIN,ROLE_USER
                test=test,enabled,ROLE_USER
                guest=guest,disabled,ROLE_USER
            </value>
        </property>
    </bean>

    <!--========================================================================
         决策管理器
    =========================================================================-->
    <bean id="accessDecisionManager"
        class="org.acegisecurity.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.acegisecurity.vote.RoleVoter" />
            </list>
        </property>
        <property name="allowIfAllAbstainDecisions" value="false" />
    </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,rememberMeFilter,exceptionFilter,securityInterceptor
            </value>     //越详细的过滤器要放前面
        </property>
    </bean>
  
 <!-- 基于URL的安全拦截器 -->
    <bean id="securityInterceptor"
        class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <property name="objectDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /admin/**=ROLE_ADMIN             //对应哪个文件夹 哪种角色才可以访问
                /user/**=ROLE_USER
            </value>
        </property>
    </bean>

   <!-- 验证用户身份 ,登陆-->
    <bean id="authenticationProcessingFilter"
        class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationFailureUrl" value="/login.jsp?login_error=Login%20failed." />
        <property name="defaultTargetUrl" value="/helloWorld.jsp" />
        <property name="filterProcessesUrl" value="/j_login.do" />
        <property name="rememberMeServices" ref="rememberMeServices" />
    </bean>
<!-- 登出-->
    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
        <!-- URL redirected to after logout -->
        <constructor-arg value="/helloWorld.jsp" />
        <constructor-arg>
            <list>
                <ref bean="rememberMeServices" />
                <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
            </list>
        </constructor-arg>
        <property name="filterProcessesUrl" value="/j_logout.do" />
    </bean>
   <!-- 记住用户登录信息   remeberMeFilter和remeberMeServices配合就实现了自动登陆功能-->
    <bean id="rememberMeFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="rememberMeServices" ref="rememberMeServices" />
    </bean>
 <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="userDetailsService" />
        <property name="parameter" value="j_remember_me" />
        <property name="key" value="remember_Me" />
        <property name="tokenValiditySeconds" value="31536000" />
    </bean>

  <!-- 处理登录异常或权限异常的Filter -->
    <bean id="exceptionFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <!-- 出现AuthenticationException时的登录入口 -->
        <property name="authenticationEntryPoint">
            <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                <property name="loginFormUrl" value="/login.jsp" />
                <property name="forceHttps" value="false" />
            </bean>
        </property>
        <!-- 出现AccessDeniedException时的Handler -->
        <property name="accessDeniedHandler">
            <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl" />
            <!-- 可选属性: property name="errorPage" value="/denied.html" -->
        </property>
    </bean>

 <!-- 从Session中获得用户信息并放入SecurityContextHolder -->
    <bean id="httpSessionContextIntegrationFilter"
        class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
-----------------------------------------完
书中p376的图10-6为该例的结构图。

Spring的配置文件:dispatcher_servlet.xml
Acegi安全框架的配置文件:security.xml

 

实例2,保护Bean组件 未完~````````

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值