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

Spring MVC 攔截器實現登入驗證:HandlerInterceptor 全流程實戰

     編輯:Java 相關知識

Spring MVC HandlerInterceptor 可在 Controller 執行前/後/完成後攔截請求,是實現登入驗證、權限檢查、日誌記錄的標準方式。本文完整示範登入攔截器實作與配置。

攔截器三個切入點

方法執行時機返回值用途
preHandleController 執行前boolean驗證、攔截、重定向;false 中斷後續流程
postHandleController 執行後、視圖渲染前void修改 Model、統一視圖數據
afterCompletion視圖渲染完成後void資源清理、耗時統計、異常處理

完整實作

1. 登入攔截器


@Component
public class LoginInterceptor implements HandlerInterceptor {

    private static final String LOGIN_URL = "/loginpage.html";
    private static final String USER_SESSION_KEY = "currentUser";

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        HttpSession session = req.getSession(false); // 不自動建立
        if (session == null || session.getAttribute(USER_SESSION_KEY) == null) {
            // 未登入:重定向到登入頁
            resp.sendRedirect(req.getContextPath() + LOGIN_URL);
            return false; // 關鍵:阻止進入 Controller
        }
        return true; // 放行
    }

    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object handler, ModelAndView mv) {
        // 可統一注入選單、用戶資訊等
        HttpSession session = req.getSession(false);
        if (session != null && mv != null) {
            mv.addObject("loginUser", session.getAttribute(USER_SESSION_KEY));
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex) {
        // 記錄請求耗時、清理 ThreadLocal 等
        if (ex != null) {
            log.error("請求異常", ex);
        }
    }
}

2. Spring MVC 配置


@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/user/**")      // 攔截用戶中心相關
                .excludePathPatterns("/loginpage.html", "/doLogin", "/static/**"); // 排除登入頁、靜態資源
    }
}

或 XML 配置:


<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <mvc:exclude-mapping path="/loginpage.html"/>
        <mvc:exclude-mapping path="/doLogin"/>
        <bean class="com.example.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

3. Controller 範例


@Controller
public class UserController {

    @PostMapping("/doLogin")
    public String login(@RequestParam String username, @RequestParam String password,
                        HttpSession session, RedirectAttributes ra) {
        User user = userService.authenticate(username, password);
        if (user != null) {
            session.setAttribute("currentUser", user);
            return "redirect:/user/home";
        }
        ra.addFlashAttribute("error", "帳號或密碼錯誤");
        return "redirect:/loginpage.html";
    }

    @GetMapping("/user/home")
    public String home() {
        return "user/home"; // 只有登入用戶能進入
    }

    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "redirect:/";
    }
}

關鍵細節與最佳實踐

項目建議
排除靜態資源務必 excludePathPatterns("/static/**", "/css/**", "/js/**"),否則圖片/CSS 也會被攔截導致 404
session.getSession(false)不自動建立 Session,避免匿名用戶產生大量無效 Session
重定向 vs 轉發攔截器中用 sendRedirect(重定向),瀏覽器地址欄變為登入頁 URL
Ajax 請求處理檢測 X-Requested-With: XMLHttpRequest,返回 401 JSON 而非重定向 HTML
多攔截器順序按 addInterceptor 順序執行;登入驗證通常放第一個
ThreadLocal 清理在 afterCompletion 清理請求級上下文,防記憶體洩漏

進階:基於註解的細粒度控制


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireLogin {}

public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
        if (handler instanceof HandlerMethod hm) {
            RequireLogin ann = hm.getMethodAnnotation(RequireLogin.class);
            if (ann != null && !isLoggedIn(req)) {
                sendUnauthorized(resp);
                return false;
            }
        }
        return true;
    }
}

Controller 方法加 @RequireLogin 即可單獨保護,無需全域路徑匹配。

總結

HandlerInterceptor 是 Spring MVC 處理橫切關注點的核心機制。登入驗證核心邏輯:preHandle 檢查 Session → 未登入 sendRedirect + return false。配合 excludePathPatterns 排除公開路徑,並在 postHandle/afterCompletion 處理共享數據與清理。

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