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

Struts 2 自定義攔截器實作:登入驗證與權限控制

     編輯:Java 相關知識

攔截器角色

Struts 2 攔截器實現 AOP(面向切面程式設計),可在 Action 執行前後插入橫切邏輯:登入驗證、日誌記錄、事務管理、資料準備等。自定義攔截器需實作 Interceptor 介面或繼承 AbstractInterceptor。

登入驗證攔截器範例

package com.example.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ServletActionContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class LoginInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession(false); // 不自動建立
        String uri = request.getRequestURI(); // 含 context path
        String actionPath = uri.substring(request.getContextPath().length()); // 純 action 路徑

        // 1. 登入頁面本身放行
        if (actionPath.endsWith("/login.action") || actionPath.endsWith("/login.jsp")) {
            return invocation.invoke();
        }

        // 2. 檢查 Session 中是否有使用者資訊
        Object user = (session != null) ? session.getAttribute("currentUser") : null;
        if (user != null) {
            return invocation.invoke(); // 已登入,放行
        }

        // 3. 未登入:重導至登入頁
        // 若為 AJAX 請求,回傳 JSON 錯誤碼而非重導
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            // 假設使用約定結果類型 "ajaxLoginRequired"
            return "ajaxLoginRequired";
        }
        return "loginRedirect"; // 對應 struts.xml 中的全域結果
    }
}

struts.xml 配置

<struts>
    <package name="default" extends="struts-default">
        <interceptors>
            <interceptor name="loginCheck" class="com.example.interceptor.LoginInterceptor"/>
            <interceptor-stack name="secureStack">
                <interceptor-ref name="loginCheck"/>
                <interceptor-ref name="defaultStack"/> <!-- 保留預設參數準備、驗證等 -->
            </interceptor-stack>
        </interceptors>

        <default-interceptor-ref name="secureStack"/>

        <global-results>
            <result name="loginRedirect" type="redirect">/login.jsp</result>
            <result name="ajaxLoginRequired" type="json">
                <param name="root">{success:false, code:401, msg:'未登入'}</param>
            </result>
        </global-results>

        <!-- 登入 Action 不需攔截,可單獨覆寫 -->
        <action name="login" class="com.example.action.LoginAction">
            <interceptor-ref name="defaultStack"/>
            <result name="success">/index.jsp</result>
            <result name="input">/login.jsp</result>
        </action>
        <!-- 其他 Action 繼承 secureStack -->
    </package>
</struts>

進階:基於註解的權限控制

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresRole {
    String[] value() default {};
}

攔截器中透過反射檢查 Action 方法上的註解,比對 Session 中使用者角色,實現細粒度授權。

常見錯誤與注意事項

  1. 攔截器為單例:不要在攔截器類中宣告非執行緒安全的實例變數(如計數器、暫存請求資料)。
  2. 順序敏感:interceptor-stack 中引用順序決定執行順序,defaultStack 內含 paramsPrepareParamsStack,參數注入發生在攔截器鏈中段,登入檢查宜放在最前。
  3. 避免無限重導:登入頁對應的 Action 必須排除攔截(如上例單獨引用 defaultStack)。
  4. Session 為 null:使用 request.getSession(false) 避免為未登入使用者建立無用 Session。

總結

自定義攔截器是 Struts 2 擴充性的核心體現。將登入驗證、權限檢查等通用邏輯從 Action 中剝離,不僅符合單一職責原則,也讓業務程式碼更專注於核心領域邏輯。

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