1. 程式人生 > >acegi security實踐教程—訪問系統中資源前必須登陸系統

acegi security實踐教程—訪問系統中資源前必須登陸系統

問題:

  處於安全形度,訪問本系統時,是需要登陸才可以訪問其下的資源。根據上篇部落格的除錯,我們發現,若其url在資料庫中沒有沒有配置其角色,則是可以直接訪問其url的。   那為了避免這種情況,我們如何改進自己的系統,進一步接近真實的企業開發呢? 概要:   這節我們將會講到匿名許可權,securitycontext中隨時都包含許可權,而不是隻有登入後才有。   進一步改進上一篇部落格中自定義objectDefinitionSource類,因為若返回null,則直接進入其url。

具體開發:
開發環境:

  MyEclispe10.7.1+tomcat6.0.37+acegi1.0.5+spring2.0+jdk1.6【其中資料庫和資料結構保持不變】 專案目錄如下:     其中readme主要用來記錄本次驗證目的

配置匿名Filter:

  
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,
anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
    <!--匿名過濾器 -->
    <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
      <!-- 其中key隨意提供一個名字即可,但是必須提供,類似使用者名稱 -->
      <property name="key" value="test"></property>
      <!-- userAttribute提供了其密碼和相應的角色 -->
      <property name="userAttribute" value="testpwd,ROLE_ANONYMOUS"></property>
    </bean>

配置原因:

  根據以往的經驗,我們還是來看其原始碼,為什麼必須提供key以及userAttribute呢?   doFilter中的:   SecurityContextHolder.getContext().setAuthentication(createAuthentication(request));   而createAuthentication程式碼如下:       protected Authentication createAuthentication(ServletRequest request) {
        Assert.isInstanceOf(HttpServletRequest.class, request,             "ServletRequest must be an instance of HttpServletRequest");         AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(),                 userAttribute.getAuthorities());         auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));         return auth;     }   而AnonymousAuthenticationToken程式碼:       public AnonymousAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) {         super(authorities);         if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (authorities == null)             || (authorities.length == 0)) {             throw new IllegalArgumentException("Cannot pass null or empty values to constructor");         }         this.keyHash = key.hashCode();         this.principal = principal;         setAuthenticated(true);     }   所以key、principal【密碼】、authorities 三個屬性必須配置,通過這三個屬性來new一個匿名的許可權,然後存放到securitycontext中,這樣SecurityContextHolder.getContext().getAuthentication()中的許可權不是null,而是匿名的許可權,其中角色資訊ROLE_ANONYMOUS 完善自定義objectDefinitionSource類:   若是保護資源,則返回資料庫中其對應的角色資訊;若不是保護資源,我們不返回null,否則直接進入其url,我們返回一個自定義角色資訊。       //若是保護的資源    if(matched){     //進一步查詢此url的角色許可權     String urlRole="select role from test_resource_role where url=?";     List<Map> roleList=this.jdbcTemplate.queryForList(urlRole,new Object[]{url});     return converURLRole(roleList);        }        ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();    configDefinition.addConfigAttribute(new SecurityConfig("IS_AUTHENTICATED_FULLY"));    return configDefinition;   這樣改進後,我們再看看AbstractSecurityInterceptor中的beforeInvocation方法:

 結果講解:

 投票失敗後,則根據錯誤分類資訊,轉向不同的頁面。  另一個注意點:  若想登陸成功後一直轉到預設頁面而非訪問的目的地時,如何操作?  比如:訪問http://localhost/acegitest8/test.jsp,首先出現login.jsp頁面,若登陸成功後,你想跳轉到預設的/userinfo.jsp頁面。跳轉之後,再訪問http://localhost/acegitest8/test.jsp。  無論何種情況,只要登陸後就轉到acegi.xml預設的配置頁面。如何配置?  AuthenticationProcessingFilter中alwaysUseDefaultTargetUrl屬性預設情況為false,所以只要我們在aceg.xml配置為true即可。        <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">           <!-- 認證管理器,然後委託給Provides -->         <property name="authenticationManager" ref="authenticationManager"/>           <!-- 認證失敗後轉向的url,包含出錯資訊的的登陸頁面 -->         <property name="authenticationFailureUrl" value="/login.jsp?login_error=1"/>           <!-- 登陸成功後轉向的url -->         <property name="defaultTargetUrl" value="/userinfo.jsp"/>           <!-- 登陸的url,這個是預設的acegi自帶的 -->         <property name="filterProcessesUrl" value="/j_acegi_security_check"/>           <!-- 永遠轉到登陸成功後預設的目的地,如上文/userinfo.jsp -->         <property name="alwaysUseDefaultTargetUrl" value="true"/>     </bean>