在使用 EasyUI 構建前端、SpringMVC 為後端框架、Shiro 做權限控制的項目中,如何優雅地處理 Session 過期後自動跳轉到登錄頁?嘗試編寫攔截器判斷 Session 卻導致所有請求被攔截,求解決方案。
Shiro 提供了完善的 Session 管理機制,可通過配置 `sessionManager` 和 `sessionDAO` 實現 Session 超時控制。在 `shiro.ini` 或 Spring 配置中設置全局超時時間,並配置 `shiroFilter` 的 `loginUrl`。當 Session 過期,Shiro 會自動重定向到登錄頁。詳細可參考:Shiro Session 管理實戰。
自定義 `HandlerInterceptor`,在 `preHandle` 中判斷 Session 是否有效,僅對需要登錄的請求攔截,排除登錄頁、靜態資源等。關鍵在於配置 `excludePathPatterns` 避免過度攔截。參考實現:SpringMVC 攔截器 Session 判斷。
public class SessionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("user") == null) {
// AJAX 請求返回 JSON 提示,普通請求重定向
String xhr = request.getHeader("X-Requested-With");
if ("XMLHttpRequest".equals(xhr)) {
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"msg\":\"Session過期,請重新登錄\"}");
} else {
response.sendRedirect(request.getContextPath() + "/login.jsp");
}
return false;
}
return true;
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login.jsp" />
<mvc:exclude-mapping path="/static/**" />
<mvc:exclude-mapping path="/logout" />
<bean class="com.example.interceptor.SessionInterceptor" />
</mvc:interceptor>
</mvc:interceptors>