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

JDBC 用戶驗證常見錯誤修正:返回值邏輯與資源關閉最佳實踐

     編輯:Java 相關知識

原始代碼問題分析


public boolean checkUser(String tid, String pwd) {
    try {
        stmt = conn.createStatement();
        rs = stmt.executeQuery("Select * from ClientId where ClientId=" + tid + " and where passWord=" + pwd + "");
    } catch (SQLException se) {
        // 錯誤處理中重複關閉資源,且未返回值 → 編譯錯誤「missing return statement」
    }
    // 邏輯錯誤:rs.isAfterLast() || rs.isBeforeFirst() 無法正確判斷是否有資料
    try {
        if (rs.isAfterLast() || rs.isBeforeFirst()) return true;
        else return false;
    } catch (SQLException se) { }
    finally { /* 關閉資源 */ }
}

主要缺陷

  1. SQL 注入風險:字串拼接未使用 `PreparedStatement`。
  2. WHERE 子句語法錯誤:`and where` 應為 `and`。
  3. 結果集判斷錯誤:`isAfterLast/isBeforeFirst` 不可靠,應用 `rs.next()`。
  4. 資源管理混亂:catch 區塊中關閉資源可能拋出異常導致 finally 失效;且編譯器檢測到某些路徑無 `return`。
  5. 連線複用問題:方法內關閉 `conn` 會導致後續調用失效。

修正版:使用 PreparedStatement + try-with-resources


public boolean checkUser(String tid, String pwd) {
    String sql = "SELECT 1 FROM ClientId WHERE ClientId = ? AND passWord = ?";
    try (Connection conn = DriverManager.getConnection(URL, USER, PASS);
         PreparedStatement ps = conn.prepareStatement(sql)) {
        ps.setString(1, tid);
        ps.setString(2, pwd);
        try (ResultSet rs = ps.executeQuery()) {
            return rs.next(); // 存在至少一筆 → true
        }
    } catch (SQLException e) {
        e.printStackTrace(); // 或拋出自定義異常
        return false;
    }
}

關鍵改進點

  • 參數化查詢:防 SQL 注入,自動處理引號轉義。
  • try-with-resources:自動關閉 `Connection`、`PreparedStatement`、`ResultSet`,順序正確,無需手動 finally。
  • 語義正確:`rs.next()` 同時完成「游標前移」與「是否有資料」判斷。
  • 連線獲取內移:方法內建立/關閉連線,避免共享連線關閉導致後續失效;生產環境請改用連線池。
  • 明確返回:所有路徑均有 `return boolean`,編譯通過。

進階建議

  • 密碼**不可明文儲存**,應儲存雜湊值(BCrypt/Argon2),驗證時比對雜湊。
  • 使用連線池(HikariCP、Druid)管理連線生命週期。
  • 記錄審計日誌(登入成功/失敗、IP、時間)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved