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

基於 Struts 的權限控制系統設計:資源樹、角色繼承與 Action 權限攔截

     編輯:Java 程式設計入門

核心領域模型

1. 資源 — 樹形結構

  • 葉子:不可分割的操作權限 (如「用戶註冊」、「修改信息」)。
  • 節點:邏輯分組 (如「用戶管理」包含上述葉子)。
  • 命名規範:namespace 風格,system.user.useradd、system.department.add、system.common。

2. 角色 — 權限集合容器

  • 綁定資源列表 (葉子) 與節點列表。
  • 節點綁定兩種模式:include=false 僅節點本身、include=true 遞歸包含所有子葉子。
  • 角色繼承:RoleD 依賴 RoleA → 擁有 RoleA 所有權限 (組合模式)。

3. 用戶 — 單一角色

  • 每用戶關聯一個角色,透過角色繼承獲得完整權限集。

Struts 整合:Action 配置擴展權限屬性

修改 struts-config.xml

<action path="/editSubscription"
    type="org.apache.struts.webapp.example.EditSubscriptionAction"
    attribute="subscriptionForm" scope="request" validate="false"
    rights="system.user"> <!-- 新增權限標識 -->
    <forward name="failure" path="/mainMenu.jsp"/>
    <forward name="success" path="/subscription.jsp"/>
</action>

擴展 ActionConfig 源碼 (Struts 1.1/1.2)

// org.apache.struts.config.ActionConfig
protected String rights = "common"; // 默認公共權限

public String getRights() { return this.rights; }

public void setRights(String rights) {
    if (configured) throw new IllegalStateException("Configuration is frozen");
    this.rights = rights;
}

重新編譯 struts-core.jar 或將修改類放在項目 classpath 前面覆蓋 (熱修補)。

權限配置文件 (XML)

<role name="01">
    <resource-list>
        <resource name="test" url="test.jsp" menu="false"/>
        <resource name="user" url="user.jsp" menu="true"/>
    </resource-list>
    <node-list>
        <node name="system.test" include="false"/> <!-- 僅節點 -->
    </node-list>
</role>

攔截實現兩種方案對比

方案實現方式優點缺點建議場景
BaseAction 模式所有 Action 繼承 BaseAction,在 execute() 首行調用 checkRight()簡單、可控、不改框架源碼強制繼承、易忘調用、AOP 感弱中小項目、團隊紀律較好
RequestProcessor 擴展繼承 RequestProcessor,覆寫 processActionPerform,在調用 Action.execute 前統一攔截完全透明、零侵入、集中控制需修改框架源碼/配置 controller、升級維護難大型項目、嚴格合規要求

RequestProcessor 擴展關鍵代碼

public class PermissionRequestProcessor extends RequestProcessor {
    @Override
    protected ActionForward processActionPerform(HttpServletRequest request,
                                                 HttpServletResponse response,
                                                 Action action, ActionForm form,
                                                 ActionMapping mapping) throws IOException, ServletException {
        // 1. 獲取當前用戶角色權限集 (從 Session/ThreadLocal)
        Set userRights = getUserRights(request);
        
        // 2. 獲取 Action 配置的所需權限
        String requiredRight = mapping.getRights(); // 需 ActionConfig 擴展支持
        
        // 3. 判斷 (支援通配符、角色繼承邏輯)
        if (!hasPermission(userRights, requiredRight)) {
            // 無權限:轉發至錯誤頁或返回 403
            request.setAttribute("errorMsg", "權限不足: " + requiredRight);
            return mapping.findForward("accessDenied"); // 需全局 forward 配置
        }
        
        // 4. 有權限:繼續標準流程
        return super.processActionPerform(request, response, action, form, mapping);
    }
}

配置 struts-config.xml:<controller processorClass="com.myapp.PermissionRequestProcessor"/>

現代化對比:Spring Security / Shiro

  • 聲明式權限:@PreAuthorize("hasAuthority('system.user')") 或 Shiro 註解,無需擴展框架核心。
  • URL 級攔截:<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>。
  • 方法級權限:Service 方法直接標註,粒度更細。
  • 資源樹管理:動態菜單、按鈕級權限、數據權限 (行級) 開箱即用。

遷移建議

  1. 保留現有 rights 屬性映射到 Spring Security ConfigAttribute。
  2. 編寫自定義 FilterInvocationSecurityMetadataSource 讀取舊 XML 配置,平滑遷移。
  3. 逐步將 BaseAction.checkRight() 替換為註解/配置,最終移除自定義 RequestProcessor。

Struts 時代的權限設計雖顯笨重,但「資源樹+角色繼承+Action 標識」的核心模型至今仍是 RBAC 系統的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved