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

Java EE Filter 實戰:自動登錄、安全攔截、黑名單封禁、註銷自動登錄全功能整合

     編輯:Java 相關知識

單一 Filter 整合多項橫切功能

通過一個 AuthFilter 串聯:編碼統一 → 安全登錄攔截 → 自動登錄恢復 → 黑名單封禁 → 放行業務。

完整 Filter 代碼

@WebFilter("/*")
public class AuthFilter implements Filter {
    private static final Set<String> BLACK_IPS = ConcurrentHashMap.newKeySet();
    private String encoding = "UTF-8";

    @Override public void init(FilterConfig cfg) {
        encoding = cfg.getInitParameter("encoding");
        // 黑名單可從 DB/Redis 載入,這裡演示靜態
        BLACK_IPS.addAll(Arrays.asList("192.168.1.100", "10.0.0.5"));
    }

    @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // 1. 編碼統一
        request.setCharacterEncoding(encoding);
        response.setContentType("text/html;charset=" + encoding);

        // 2. 黑名單封禁(最優先,節省資源)
        String ip = request.getRemoteAddr();
        if (BLACK_IPS.contains(ip)) {
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write("您的 IP 已被封禁 <a href='" + request.getContextPath() + "/login.jsp'>登錄頁</a>");
            return;
        }

        // 3. 安全登錄攔截:排除靜態資源、登錄頁、註冊頁
        String uri = request.getRequestURI();
        if (isExcluded(uri)) { chain.doFilter(request, response); return; }

        HttpSession session = request.getSession(false);
        String user = (session != null) ? (String) session.getAttribute("user") : null;

        // 4. 自動登錄恢復
        if (user == null) {
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie c : cookies) if ("autoLogin".equals(c.getName())) {
                    String[] uv = c.getValue().split("\\|", 2);
                    if (uv.length == 2) {
                        String name = URLDecoder.decode(uv[0], "UTF-8");
                        String pwd = URLDecoder.decode(uv[1], "UTF-8");
                        if (userService.validate(name, pwd)) { // 驗證 DB
                            request.getSession(true).setAttribute("user", name);
                            user = name; break;
                        }
                    }
                }
            }
        }

        // 5. 最終放行或攔截
        if (user != null) {
            chain.doFilter(request, response);
        } else {
            response.sendRedirect(request.getContextPath() + "/login.jsp");
        }
    }

    private boolean isExcluded(String uri) {
        return uri.endsWith("/login.jsp") || uri.endsWith("/login.do")
                || uri.contains("/static/") || uri.contains("/css/") || uri.contains("/js/");
    }
    @Override public void destroy() {}
}

登錄 Servlet(生成自動登錄 Cookie)

@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
    @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String name = req.getParameter("name"), pwd = req.getParameter("pwd");
        int days = Integer.parseInt(req.getParameter("remember")); // 0/1/7
        if (userService.validate(name, pwd)) {
            req.getSession().setAttribute("user", name);
            if (days > 0) {
                String val = URLEncoder.encode(name, "UTF-8") + "|" + URLEncoder.encode(pwd, "UTF-8");
                Cookie c = new Cookie("autoLogin", val);
                c.setMaxAge(days * 86400); c.setPath(req.getContextPath());
                resp.addCookie(c);
            }
            resp.sendRedirect(req.getContextPath() + "/index.jsp");
        } else {
            req.getSession().setAttribute("error", "用戶名或密碼錯誤");
            resp.sendRedirect(req.getContextPath() + "/login.jsp");
        }
    }
}

註銷自動登錄 Servlet

@WebServlet("/cancelAutoLogin")
public class CancelAutoLoginServlet extends HttpServlet {
    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Cookie c = new Cookie("autoLogin", "");
        c.setMaxAge(0); c.setPath(req.getContextPath());
        resp.addCookie(c);
        resp.sendRedirect(req.getContextPath() + "/index.jsp");
    }
}

前端登錄頁片段

<c:if test="${empty sessionScope.user}">
  <form action="<c:url value='/login.do'/>" method="post">
    用戶名:<input name="name"/><br/>
    密碼:<input name="pwd" type="password"/><br/>
    不自動登錄 <input type="radio" name="remember" value="0" checked/>
    1 天 <input type="radio" name="remember" value="1"/>
    7 天 <input type="radio" name="remember" value="7"/><br/>
    <input type="submit" value="登錄"/>
  </form>
</c:if>
<c:if test="${!empty sessionScope.user}">
  歡迎 ${sessionScope.user} <a href="<c:url value='/cancelAutoLogin'/>">取消自動登錄</a>
</c:if>

生產環境加固建議

  • 密碼絕不存 Cookie,應存加密 Token(JWT/隨機字串+Redis 映射)
  • 黑名單接入 Redis + 定時同步 DB,支援熱更新
  • 排除靜態資源路徑,避免 CSS/JS 被攔截導致頁面樣式缺失
  • 自動登錄 Token 設置 HttpOnly、Secure、SameSite=Lax
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved