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

Java Servlet 實現用戶登錄驗證完整示例:從表單提交到 Session 管理

     編輯:Java 程式設計入門

項目結構概覽

src/
├── com/ncu/
│   ├── login.java          // 登錄頁面 Servlet (GET)
│   ├── LoginPro.java       // 登錄處理 Servlet (POST)
│   └── Welcome.java        // 歡迎頁 Servlet (GET)
└── web.xml                 // Servlet 映射配置

核心代碼實現

1. 登錄頁面 —— login.java (GET 請求)

職責:輸出 HTML 登錄表單,action 指向處理 Servlet。

package com.ncu;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class login extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        resp.setContentType("text/html;charset=UTF-8");  // 建議 UTF-8
        PrintWriter out = resp.getWriter();
        
        out.println("");
        out.println("用戶登錄");
        out.println("

用戶登錄界面

"); out.println("
"); out.println("用戶名:
"); out.println("密碼:
"); out.println(""); out.println("
"); } }

改進點:使用 UTF-8 編碼;HTML 結構規範;表單 method=post 保護密碼不顯示在 URL。

2. 登錄驗證 —— LoginPro.java (POST 請求)

職責:接收參數、驗證憑證、建立會話、重定向。

package com.ncu;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginPro extends HttpServlet {
    // 實際項目應從數據庫/配置讀取,此處僅演示
    private static final String VALID_USER = "nicolas";
    private static final String VALID_PWD  = "nicolas";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String user = req.getParameter("userName");
        String pwd  = req.getParameter("Pwd");
        
        // 參數防空
        if (user == null) user = "";
        if (pwd == null) pwd = "";
        
        if (VALID_USER.equals(user) && VALID_PWD.equals(pwd)) {
            // 驗證成功:創建 Session,存儲用戶標識
            HttpSession session = req.getSession(true);
            session.setAttribute("loginUser", user);
            session.setMaxInactiveInterval(30 * 60); // 30 分鐘超時
            
            // 重定向到歡迎頁(避免表單重複提交)
            resp.sendRedirect(req.getContextPath() + "/welcome");
        } else {
            // 驗證失敗:重定向回登錄頁,可攜帶錯誤提示
            resp.sendRedirect(req.getContextPath() + "/login?error=1");
        }
    }
}

關鍵最佳實踐:

  • 使用 HttpSession 維持登錄狀態,而非 URL 重寫或隱藏字段。
  • 登錄成功後 重定向 (sendRedirect) 而非轉發,防止瀏覽器刷新重複提交 POST。
  • 設置 session.setMaxInactiveInterval() 控制超時。
  • 生產環境必須使用 BCrypt/Argon2 加密存儲密碼,絕不存明文。

3. 歡迎頁 —— Welcome.java (GET 請求)

職責:校驗 Session,顯示個性化歡迎或重定向登錄。

package com.ncu;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class Welcome extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        HttpSession session = req.getSession(false); // 不創建新 Session
        String user = (session != null) ? (String) session.getAttribute("loginUser") : null;
        
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        
        if (user != null) {
            out.println("

歡迎," + user + "!

"); out.println("退出登錄"); } else { // 未登錄或 Session 失效,重定向登錄頁 resp.sendRedirect(req.getContextPath() + "/login"); } } }

4. 登出 Servlet(補充)


@WebServlet("/logout")
public class Logout extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        HttpSession session = req.getSession(false);
        if (session != null) session.invalidate(); // 銷毀 Session
        resp.sendRedirect(req.getContextPath() + "/login");
    }
}

web.xml 完整配置 (Servlet 3.0+ 可改用 @WebServlet 註解)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="https://java.sun.com/xml/ns/javaee"
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://java.sun.com/xml/ns/javaee 
    https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>LoginDemo</display-name>

    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.ncu.login</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>loginpro</servlet-name>
        <servlet-class>com.ncu.LoginPro</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>loginpro</servlet-name>
        <url-pattern>/loginpro</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>welcome</servlet-name>
        <servlet-class>com.ncu.Welcome</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>welcome</servlet-name>
        <url-pattern>/welcome</url-pattern>
    </servlet-mapping>

    <!-- 可選:Session 超時配置(分鐘) -->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file>login</welcome-file>  <!-- 默認進入登錄頁 -->
    </welcome-file-list>
</web-app>

進階:使用 Filter 實現統一登錄攔截

避免在每個 Servlet 重複檢查 Session,編寫 LoginFilter:


@WebFilter(urlPatterns = {"/welcome", "/user/*", "/admin/*"})
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpSession session = req.getSession(false);
        
        if (session != null && session.getAttribute("loginUser") != null) {
            chain.doFilter(request, response); // 已登錄,放行
        } else {
            resp.sendRedirect(req.getContextPath() + "/login"); // 未登錄,跳轉
        }
    }
}

在 web.xml 或註解中註冊 Filter 即可實現全站權限控制。

安全加固清單

風險防範措施
密碼明文傳輸全站強制 HTTPS (TLS 1.2+)
密碼明文存儲BCrypt/Argon2 + Salt 哈希存儲
暴力破解登錄失敗計數 + 驗證碼 + 帳號鎖定策略
Session 劫持HttpOnly、Secure 標記;定期輪換 Session ID
CSRF 攻擊關鍵操作驗證 CSRF Token (雙重提交 Cookie 模式)
SQL 注入使用 PreparedStatement / ORM 參數綁定

總結

本示例展示了基於 Servlet + Session 的經典登錄流程:

  1. login (GET) → 渲染表單
  2. LoginPro (POST) → 驗證 → 建立 Session → 重定向
  3. Welcome (GET) → 校驗 Session → 顯示內容或跳轉
  4. Logout → 銷毀 Session

實際項目中建議:

  • 使用 Spring Security / Apache Shiro 等成熟框架處理認證授權。
  • 前後端分離架構下改用 JWT (JSON Web Token) 無狀態認證。
  • 引入 OAuth2 / OpenID Connect 支持第三方登錄 (微信、Google、企業 SSO)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved