首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring + Acegi + Hibernate + Struts 2 實現基於角色的權限控制 (RBAC) 完整實戰

     編輯:Java 相關知識

架構選型理由

傳統硬編碼安全檢查耦合業務邏輯,複用性差。Spring AOP + Acegi Security (現 Spring Security 前身) 提供聲明式、可插拔的安全框架,配合 Java 5 註解極大簡化配置。

技術棧版本

  • Java 5, Tomcat 5.5.26
  • Struts 2.0.11, Spring 2.5.1
  • Hibernate 3.2, Acegi 1.0.6

數據模型 (三表支撐 RBAC)

User: id, enable, user_name, user_pass, email_box
RoleInfo: id, role_name, role_title, descp
UserRole: user_id, user_name, role_id, role_name  -- 多對多關聯

-- 種子數據
Role: ROLE_USER, ROLE_ADMIN
User1: ROLE_USER + ROLE_ADMIN
User2: ROLE_USER
User3: 無角色

核心配置 acegi-security.xml

1. 認證管理器

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
  <property name="providers">
    <list>
      <ref bean="daoAuthenticationProvider"/>
      <ref bean="rememberMeAuthenticationProvider"/>
    </list>
  </property>
</bean>

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="userDetailsService" ref="userDetailsService"/>
</bean>

<bean id="userDetailsService" class="org.ymcn.security.AcegiUserDetailsService">
  <property name="userDao" ref="userDao"/>
  <property name="userRoleDao" ref="userRoleDao"/>
</bean>

2. 決策管理器 (基於角色前綴投票)

<bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
  <property name="decisionVoters">
    <list><ref bean="roleVoter"/></list>
  </property>
  <property name="allowIfAllAbstainDecisions" value="false"/>
</bean>
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
  <property name="rolePrefix" value="ROLE_"/>
</bean>

3. 過濾器鏈 (URL 級安全攔截)

<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>

<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
      /cart/previeworder*=ROLE_USER
    </value>
  </property>
</bean>

關鍵過濾器:authenticationProcessingFilter (登錄)、rememberMeFilter (記住我)、exceptionFilter (異常轉向登錄/拒絕頁)。

web.xml 整合

<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-mapping>
  <filter-name>acegiFilterChain</filter-name>
  <url-pattern>*.j</url-pattern>
</filter-mapping>
<!-- 必須在 Struts2 Filter 前面 -->

方法級安全 (AOP 代理)

<!-- 安全攔截器 -->
<bean id="serviceSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="accessDecisionManager" ref="accessDecisionManager"/>
  <property name="objectDefinitionSource">
    <bean class="org.acegisecurity.intercept.method.MethodDefinitionAttributes">
      <property name="attributes">
        <bean class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/>
      </property>
    </bean>
  </property>
</bean>

<!-- 自動代理目標 Service -->
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="interceptorNames">
    <list><value>transactionInterceptor</value><value>serviceSecurityInterceptor</value></list>
  </property>
  <property name="beanNames">
    <list><value>userService</value><value>mailService</value></list>
  </property>
</bean>

唯一業務代碼:AcegiUserDetailsService

public class AcegiUserDetailsService implements UserDetailsService {
    private UserDao userDao;
    private UserRoleDao userRoleDao;

    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
        User user = userDao.getUserByName(userName);
        if (user == null) throw new UsernameNotFoundException("User not found");

        List<UserRole> roles = userRoleDao.getUserRoleByUserName(userName);
        if (roles == null || roles.isEmpty()) throw new UsernameNotFoundException("No roles");

        GrantedAuthority[] authorities = new GrantedAuthority[roles.size()];
        int i = 0;
        for (UserRole r : roles) {
            authorities[i++] = new GrantedAuthorityImpl(r.getRoleName().toUpperCase());
        }
        return new org.acegisecurity.userdetails.User(
            userName, user.getUserPass(), true, true, true, true, authorities);
    }
    // Setter 省略
}

核心職責:根據用戶名查詢用戶與角色,構建 UserDetails 返回。密碼驗證、會話管理均由框架自動處理。

業務層聲明式授權

public interface MailService {
    @Secured({"ROLE_USER"})
    void sendSimpleMail(Long userId);

    @Secured({"ROLE_ADMIN"})
    void sendAttachmentMail() throws Exception;
}

在介面或實現類方法上標註 @Secured,框架自動織入權限檢查。

總結

  1. 新增 acegi-security.xml、web.xml 過濾器、applicationContext.xml AOP 代理
  2. 實現 UserDetailsService 接入數據層
  3. 業務方法加 @Secured 註解
  4. 零侵入業務邏輯,完全可插拔
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved