Session 是瀏覽器級共享的** (同域名下所有標籤頁共用 `JSESSIONID` Cookie)。
// LoginServlet / Controller
session.setAttribute("LOGIN_USER", userVO); // 統一鍵名
@WebFilter("/*") // 或配置 url-pattern 排除靜態資源、登錄頁
public class AuthenticationFilter implements Filter {
private static final String[] EXCLUDE_PATHS = {"/login", "/css/", "/js/", "/images/", "/logout"};
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String uri = request.getRequestURI();
// 1. 排除無需驗證路徑
if (isExcluded(uri)) {
chain.doFilter(request, response);
return;
}
// 2. 檢查 Session 登錄標識
HttpSession session = request.getSession(false); // 不創建新 Session
Object loginUser = (session != null) ? session.getAttribute("LOGIN_USER") : null;
if (loginUser == null) {
// 3. 未登錄 → 重定向登錄頁 (攜帶目標 URL 可選)
String loginUrl = request.getContextPath() + "/login.jsp";
response.sendRedirect(loginUrl);
return;
}
// 4. 已登錄 → 放行
chain.doFilter(request, response);
}
private boolean isExcluded(String uri) {
for (String path : EXCLUDE_PATHS) {
if (uri.startsWith(request.getContextPath() + path)) return true;
}
return false;
}
}
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
HttpSession session = req.getSession(false);
if (session != null) {
session.invalidate(); // 銷毀 Session
}
// 刪除 JSESSIONID Cookie (可選,防瀏覽器保留)
Cookie cookie = new Cookie("JSESSIONID", "");
cookie.setMaxAge(0);
cookie.setPath(req.getContextPath());
resp.addCookie(cookie);
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
若需**所有標籤頁即時感知登出** (無需刷新),需引入: