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

Struts 2 權限控制實戰:從攔截器到註解的完整方案

     編輯:Java 相關知識

核心需求:雙重防線守護 Web 資源

在 Struts 2 架構下,權限控制必須覆蓋兩個維度:

  1. URL/Action 級攔截:阻擋未授權請求進入業務邏輯。
  2. 頁面元素級控制:JSP 標籤動態隱藏無權限按鈕/連結,提升體驗並防誤操作。

方案一:自定義攔截器實現聲明式權限檢查(推薦)

利用 Struts 2 攔截器鏈機制,在 Action 執行前統一驗證。

1. 定義權限註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermission {
    String value(); // 權限標識,如 "user:create"
}

2. 實作權限攔截器

public class PermissionInterceptor extends AbstractInterceptor {
    private static final Logger LOG = LoggerFactory.getLogger(PermissionInterceptor.class);

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionProxy proxy = invocation.getProxy();
        String namespace = proxy.getNamespace();
        String actionName = proxy.getActionName();
        String methodName = proxy.getMethod();

        // 1. 獲取當前登入用戶 (假設存放在 Session)
        UserPrincipal user = (UserPrincipal) ActionContext.getContext().getSession().get("USER_PRINCIPAL");
        if (user == null) {
            LOG.warn("未登入用戶嘗試訪問: {}/{}", namespace, actionName);
            return "login"; // 全域結果類型對應登入頁
        }

        // 2. 讀取方法級註解
        Method method = invocation.getAction().getClass().getMethod(methodName);
        RequiresPermission rp = method.getAnnotation(RequiresPermission.class);
        if (rp != null) {
            String requiredPerm = rp.value();
            if (!user.hasPermission(requiredPerm)) {
                LOG.warn("用戶 {} 缺少權限 {} 訪問 {}.{}", user.getUsername(), requiredPerm, actionName, methodName);
                return "unauthorized"; // 對應 403 頁面
            }
        }
        return invocation.invoke();
    }
}

3. struts.xml 註冊與引用

<package name="secure" extends="struts-default">
    <interceptors>
        <interceptor name="permCheck" class="com.example.interceptor.PermissionInterceptor"/>
        <interceptor-stack name="secureStack">
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="permCheck"/>
        </interceptor-stack>
    </interceptors>
    
    <default-interceptor-ref name="secureStack"/>
    
    <global-results>
        <result name="login">/login.jsp</result>
        <result name="unauthorized">/403.jsp</result>
    </global-results>
</package>

4. Action 使用範例

@Namespace("/admin")
@Action(value = "user", results = { @Result(name="success", location="/user/list.jsp") })
public class UserAction extends ActionSupport {
    @RequiresPermission("user:create")
    public String create() { ... }
    
    @RequiresPermission("user:delete")
    public String delete() { ... }
}

方案二:JSP 標籤庫實現頁面級權限渲染

自定義標籤 <sec:hasPermission>,配合 CSS/JS 隱藏元素:

<%@ taglib prefix="sec" uri="/security-tags" %>

<sec:hasPermission permission="user:create">
    <button id="btnAddUser">新增用戶</button>
</sec:hasPermission>

<sec:lacksPermission permission="user:delete">
    <script>$('#btnDeleteUser').hide();</script>
</sec:lacksPermission>

標籤實現核心邏輯:從 Session 取得 UserPrincipal,調用 hasPermission(String) 判斷,決定是否輸出 BodyContent。

進階:整合 Spring Security 替代自建體系

若專案已引入 Spring,強烈建議直接使用 Spring Security:

  • Filter 鏈更早攔截(Servlet 級),效能更好。
  • 支援 @PreAuthorize("hasAuthority('user:create')") 方法級安全。
  • 提供 CSRF 保護、Session 固定攻擊防禦、OAuth2/JWT 整合等企業級特性。

Struts 2 整合方式:web.xml 配置 DelegatingFilterProxy,Action 由 Spring 管理,註解即時生效。

總結:分層防禦最可靠

層級技術防禦目標
Servlet FilterSpring Security / 自定義 Filter靜態資源、早期惡意請求攔截
Struts InterceptorPermissionInterceptor + 註解Action/方法級業務權限控制
View (JSP/FTL)自定義標籤 / Thymeleaf SecUI 元素動態顯隱,體驗優化
Service/DAO程式化檢查 / AOP核心資料操作最後一道防線

權限系統設計原則:預設拒絕、最小權限、集中配置、審計日誌。切勿將權限邏輯硬編碼在 Action 內部,應透過攔截器/AOP 實現橫切關注點分離。

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