1. 程式人生 > >acegi-security 學習筆記

acegi-security 學習筆記

acegi security 是基於spring framework 開源安全解決方案。按自己的理解,其功能主要是提供了一個WEB應用安全解決方案框架。並提供了一些預設的實現。
所以,如果我們的應用中需要引入這套解決方案的話,可以根據自己的應用需求進行相應的擴充。
另外,由於acegi security 是基於spring framework 的,所以可以和現有的基於spring framework 比較容易整合。也可以和其他java web應用進行整合(關於如何在自己的系統中引入acegi security,會在後面說明自己的理解)。


自己的學習過程:
1、獲取相應的acegi security 製品,包括編譯後的製品、原始碼和例子。
2、閱讀acegi security 提供的文件,進行簡要的瞭解;
3、配置例子的執行環境,熟悉例子實現的功能;
4、結合例子,一步步的學習原始碼的實現,
5、結合文件介紹,對acegi security 進行了解。
6、編寫自己的例子,驗證、加深自己對acegi security的理解。

關於acegi security 比較詳細準確的理論介紹不再進行,這方面文件中已經有比較詳細的介紹。

請求web資源時,acegi security 的作用過程:
首先,需要在web.xml中,引入acegi security 提供的filter

<filter>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
        <param-name>targetClass</param-name>
        <param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 
這裡定義的filter只是一個filter入口,真正會對請求進行處理的是 targetClass : net.sf.acegisecurity.util.FilterChainProxy,
其相關配置資訊   在spring context的配置檔案applicationContext-acegi-security.xml 中有配置:  
  <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
      <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
        /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter,switchUserProcessingFilter
      </value>
    </property>
  </bean>
 
然後,進入請求處理過程。關於這個bean的定義資訊 我們主要是看filter鏈的定義。這些filter 鏈bean在同一個context 檔案中都可以找到。

我們可以一個個去看相應filter的配置資訊,以及參看原始碼實現,瞭解功能。
其中對web路徑請求的認證中,我們需要了解一下securityEnforcementFilter
  <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
    <property name="filterSecurityInterceptor"><ref local="filterInvocationInterceptor"/></property>
    <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>
  </bean>
這裡,主要是filterInvocationInterceptor,
  <bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
    <property name="authenticationManager"><ref bean="authenticationManager"/></property>
    <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
    <property name="objectDefinitionSource">
      <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /wo.html=ROLE_ANONYMOUS,ROLE_USER
    /index.jsp=ROLE_ANONYMOUS,ROLE_USER
    /hello.htm=ROLE_ANONYMOUS,ROLE_USER
    /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
    /switchuser.jsp=ROLE_SUPERVISOR
    /j_acegi_switch_user=ROLE_SUPERVISOR
    /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
  /**=ROLE_USER
      </value>
    </property>
  </bean>
 
  在此,主要對objectDefinitionSource值進行處理。這裡配置了很多path=role ,
  其作用就是在請求指定的路徑時,是需要當前使用者具有對應的角色的,如果具有相應角色,則正常訪問。否則跳轉至登入頁面,定義如下
  <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
    <property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
    <property name="forceHttps"><value>false</value></property>
  </bean>
  loginFormUrl 即是 登入頁面的路徑。
  authenticationProcessingFilter 定義了登入認證時出現的集中情況的處理。
  <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
    <property name="authenticationManager"><ref bean="authenticationManager"/></property>
    <property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property>
    <property name="defaultTargetUrl"><value>/</value></property>
    <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
    <property name="rememberMeServices"><ref local="rememberMeServices"/></property>
  </bean>
 
  登入成功之後,返回登入前最後一次請求的頁面。
   
至此,web路徑的請求處理過程主線完成。
這裡需要說明的就是/index.jsp=ROLE_ANONYMOUS,ROLE_USER 這裡的角色,ROLE_是標記,ANONYMOUS 是角色名稱。ANONYMOUS是隻可以匿名訪問,
這個角色無需定義。而ROLE_USER 中的USER則是使用者定義的,接下來我們介紹這部分:

使用者角色管理:
acegi security提供了使用者角色的獲取介面,以及一個預設的實現(包括對應的資料庫表定義)
  <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
    <property name="dataSource"><ref bean="dataSource"/></property>
  </bean>
可參看這裡的net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl,需要注意的是這個dao的實現是同acegi security提供的表定義一致的。
如果這個角色和使用者處理模型不能滿足自己的需要,自己可以提供自己的實現。只需要將<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
修改成自己類實現即可。

從嚴格意義上來說,以下許可權部分的介紹應該不在acegi security處理的範圍之內,不過acegi security是提供了相應的機制的:
許可權管理
許可權在acegi security 主要以acl的概念出現:即 access control list
  <bean id="basicAclExtendedDao" class="net.sf.acegisecurity.acl.basic.jdbc.JdbcExtendedDaoImpl">
    <property name="dataSource"><ref bean="dataSource"/></property>
  </bean>
  這個類實現中有acl的產生,獲取和刪除操作
 
應用資料許可權的處理:
  如果我們應用資料的許可權要藉助於acegi security 來實現的話,那主要工作就是呼叫 basicAclExtendedDao 中的相關方法。閱讀basicAclExtendedDao即可明白。
 

以上簡要的介紹了一下自己學習acegi security的一些瞭解。自己最後得出的結論是,如果自己的應用規模很小,完全可以不用acegi security。
如果要用acegi security,很多時候是需要重新實現自己的許可權和使用者模型的。