文章目錄
- Java SQL 注入防御方法
- 類型轉換
- 預編譯查詢(PreparedStatement)
- 使用 ORM 框架(如 MyBatis、Hibernate)
- 白名單限制
- ORDER BY 語句
- LIKE 語句
- 限制數據庫權限
- 過濾和轉義特殊字符
- 監控與日志審計
- 使用 Web 應用防火墻(WAF)
Java SQL 注入防御方法
類型轉換
Java 是強類型語言,因此直接的數值型 SQL 注入較少,但仍需要注意參數類型的安全性。
int id = Integer.valueOf(req.getParameter("id"));
這樣可以確保 id
變量是整數,避免輸入 1 OR 1=1
之類的 SQL 語句攻擊。
預編譯查詢(PreparedStatement)
預編譯(Parameterized Queries)是防止 SQL 注入的最佳實踐,能夠確保用戶輸入的數據不會被解析為 SQL 代碼。
public User getUserById(String id) throws SQLException {Connection connection = JDBCTOOLS.getConnection(); // 獲取數據庫連接String sql = "SELECT id, username FROM user WHERE id = ?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, id);ResultSet resultSet = preparedStatement.executeQuery();if (resultSet.next()) {return new User(resultSet.getInt("id"), resultSet.getString("username"));}return null;
}
使用 ORM 框架(如 MyBatis、Hibernate)
ORM 框架能夠自動處理 SQL 預編譯,減少 SQL 注入的風險。
@Mapper
public interface CategoryMapper {@Select("SELECT * FROM category_ WHERE name = #{name}")Category getByName(String name);
}
白名單限制
某些情況下,用戶輸入可能用于 ORDER BY
、IN
、LIKE
等 SQL 語句,預編譯無法有效防止注入。這時可使用白名單校驗。
ORDER BY 語句
private String checkSort(String sortBy) {List<String> columns = Arrays.asList("id", "username", "email");return columns.contains(sortBy) ? sortBy : "id";
}
這里通過 checkSort 方法,限定 ORDER BY 只能使用 白名單中的字段(id、username、email),如果 sortBy 不是合法字段,則默認按 id 排序。
String sql = "SELECT * FROM users ORDER BY " + checkSort(sortColumn);
LIKE 語句
String sql = "SELECT * FROM users WHERE username LIKE CONCAT('%', ?, '%')";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, userInput);
這里使用了 預編譯(PreparedStatement),將 userInput 作為參數傳遞,而不是直接拼接到 SQL 語句中。
限制數據庫權限
數據庫用戶權限應遵循最小權限原則,避免 root
賬戶執行 SQL 語句。
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'XXXX';
1、CREATE USER:在 MySQL 數據庫中創建一個新用戶。
2、‘app_user’@‘localhost’:用戶名是 app_user。
3、@‘localhost’ 指定該用戶只能從本機(localhost)連接到數據庫,不能從其他 IP 訪問。
4、IDENTIFIED BY ‘XXXX’:設置該用戶的密碼為 ‘XXXX’。
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'app_user'@'localhost';
1、GRANT:授予數據庫權限。
2、SELECT, INSERT, UPDATE:允許 app_user 在數據庫 mydb 中執行 查詢(SELECT)、插入(INSERT)、更新(UPDATE) 操作。
3、ON mydb.*
:作用范圍是 mydb 數據庫中的所有表(* 代表所有表)。
4、TO ‘app_user’@‘localhost’:只將這些權限授予 本機的 app_user。
過濾和轉義特殊字符
可以對用戶輸入進行嚴格的字符過濾,但不建議完全依賴此方法。
public static String sanitize(String input) {return input.replaceAll("[';--]", "");
}
replaceAll() 會將單引號 (')、分號 (;
)、雙減號 (–)替換為空字符串 “”,即刪除這些字符。
監控與日志審計
記錄 SQL 查詢日志,并監控異常 SQL 訪問。
LOGGER.warn("SQL Query Attempt: " + sqlQuery);
使用 Web 應用防火墻(WAF)
部署 WAF(如 ModSecurity)可以檢測和阻止 SQL 注入攻擊。