首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JSP 修改資料庫密碼完整流程:從表單提交到 UPDATE 參數化執行

     編輯:程式設計綜合問答

業務流程概覽

  1. 使用者點擊「修改密碼」按鈕 → 彈出修改表單 (舊密碼、新密碼、確認新密碼)
  2. 前端驗證 (非空、長度、兩次新密碼一致)
  3. 提交至 Servlet/Controller
  4. 後端驗證舊密碼正確性 → 執行參數化 UPDATE
  5. 回應結果 (成功/失敗訊息)

資料庫表結構假設

CREATE TABLE userInfo (
    userId INT PRIMARY KEY AUTO_INCREMENT,
    userName VARCHAR(50) NOT NULL UNIQUE,
    userPwdz VARCHAR(255) NOT NULL,  -- 建議儲存 BCrypt 雜湊而非明文
    email VARCHAR(100)
);

前端 JSP 表單 (修改密碼彈窗)

<%@ page contentType="text/html;charset=UTF-8" %>
<form id="pwdForm" action="ChangePasswordServlet" method="post">
  <input type="hidden" name="userId" value="${sessionScope.user.userId}" />
  <div>
    <label>舊密碼:</label>
    <input type="password" name="oldPwd" required />
  </div>
  <div>
    <label>新密碼:</label>
    <input type="password" name="newPwd" required minlength="6" />
  </div>
  <div>
    <label>確認新密碼:</label>
    <input type="password" name="confirmPwd" required />
  </div>
  <button type="submit">確認修改</button>
  <button type="button" onclick="closeModal()">取消</button>
</form>
<script>
// 簡易前端驗證
document.getElementById('pwdForm').addEventListener('submit', function(e) {
  const np = this.newPwd.value, cp = this.confirmPwd.value;
  if (np !== cp) { alert('兩次新密碼不一致'); e.preventDefault(); }
});
</script>

後端 Servlet 核心邏輯 (重點:參數化查詢)

@WebServlet("/ChangePasswordServlet")
public class ChangePasswordServlet extends HttpServlet {
    // 資料庫連線池建議使用 HikariCP / Druid,此處簡化為單一連線
    private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASS = "password";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String userId = req.getParameter("userId");
        String oldPwd = req.getParameter("oldPwd");
        String newPwd = req.getParameter("newPwd");
        String confirmPwd = req.getParameter("confirmPwd");

        // 1. 基本驗證
        if (userId == null || !newPwd.equals(confirmPwd)) {
            sendError(resp, "參數錯誤或兩次新密碼不一致");
            return;
        }

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {
            // 2. 驗證舊密碼 (查詢雜湊值比對)
            String checkSql = "SELECT userPwdz FROM userInfo WHERE userId = ?";
            try (PreparedStatement ps = conn.prepareStatement(checkSql)) {
                ps.setInt(1, Integer.parseInt(userId));
                try (ResultSet rs = ps.executeQuery()) {
                    if (!rs.next()) { sendError(resp, "使用者不存在"); return; }
                    String storedHash = rs.getString("userPwdz");
                    // 此處假設使用 BCrypt,實際專案請引入 jbcrypt 或 Spring Security Crypto
                    if (!BCrypt.checkpw(oldPwd, storedHash)) { 
                        sendError(resp, "舊密碼錯誤"); return; 
                    }
                }
            }

            // 3. 更新新密碼 (參數化 UPDATE,無星號、無拼接)
            String updateSql = "UPDATE userInfo SET userPwdz = ? WHERE userId = ?";
            try (PreparedStatement ps = conn.prepareStatement(updateSql)) {
                String newHash = BCrypt.hashpw(newPwd, BCrypt.gensalt(12)); // 加鹽雜湊
                ps.setString(1, newHash);
                ps.setInt(2, Integer.parseInt(userId));
                int rows = ps.executeUpdate();
                if (rows > 0) {
                    resp.getWriter().write("密碼修改成功");
                } else {
                    sendError(resp, "更新失敗,請稍後再試");
                }
            }
        } catch (SQLException | NumberFormatException e) {
            e.printStackTrace();
            sendError(resp, "系統錯誤: " + e.getMessage());
        }
    }

    private void sendError(HttpServletResponse resp, String msg) throws IOException {
        resp.setContentType("text/plain;charset=UTF-8");
        resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        resp.getWriter().write(msg);
    }
}

關鍵安全提醒

  • 絕不儲存明文密碼:務必使用 BCrypt、PBKDF2 或 Argon2 進行加鹽雜湊。
  • 參數化查詢:`PreparedStatement` 使用 `?` 佔位符,完全杜絕 SQL Injection。
  • HTTPS 傳輸:生產環境強制 TLS 1.2+,防止密碼在網路傳輸中被竊聽。
  • 舊密碼驗證:修改密碼必須驗證舊密碼,防止 Session 劫持後竄改。

常見錯誤修正

錯誤寫法正確寫法說明
`UPDATE userInfo SET userPwdz = '" + newPwd + "'``UPDATE userInfo SET userPwdz = ?`字串拼接導致 SQL Injection
`ps.setString(1, "*" + newPwd + "*")``ps.setString(1, newHash)`星號非 SQL 語法,參數直接傳值
直接比對明文 `oldPwd == rs.getString("pwd")``BCrypt.checkpw(oldPwd, storedHash)`明文比對極度不安全

總結

JSP 修改資料庫密碼的標準流程:前端表單驗證 → Servlet 接收參數 → `PreparedStatement` 參數化查詢驗證舊密碼 → 參數化 UPDATE 寫入新密碼雜湊值。核心原則:**參數化查詢 + 密碼雜湊儲存 + HTTPS 傳輸**。

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