使用JdbcTemplate/JdbcClient构建安全SQL,规避IntelliJ不安全警告
解决JdbcTemplate/JdbcClient拼接SQL常量触发IntelliJ不安全提示的问题
问题场景
习惯通过定义静态常量拼接SQL语句,示例代码如下:
public static final String TABLE_NAME = "USERS"; public static final String COLUMN_ACCOUNTID = "ACCOUNTID"; public static final String SELECT_BY_ACCOUNTID = "SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_ACCOUNTID + "=?";
但调用该SQL时,IntelliJ会提示该字符串存在不安全风险:
public Optional<User> getUserByAccountId(String accountId) { return jdbcClient // IntelliJ warns that this string is unsafe: .sql(UserSql.SELECT_BY_ACCOUNTID) .query(new UserMapper()) .param(accountId) .optional(); }
解决方法
1. 直接硬编码表名/列名到SQL常量中
放弃字符串拼接,直接在SQL常量里写死表名和列名,让IntelliJ能直接解析完整的静态SQL,消除安全提示:
public static final String SELECT_BY_ACCOUNTID = "SELECT * FROM USERS WHERE ACCOUNTID=?";
2. 使用Spring的SqlIdentifier封装表名/列名
如果需要保留表名、列名的常量定义,用Spring提供的SqlIdentifier类来封装,它是专门用于安全标识SQL对象的类型,IntelliJ能识别这种拼接是安全的:
import org.springframework.jdbc.core.SqlIdentifier; public static final SqlIdentifier TABLE_NAME = SqlIdentifier.of("USERS"); public static final SqlIdentifier COLUMN_ACCOUNTID = SqlIdentifier.of("ACCOUNTID"); public Optional<User> getUserByAccountId(String accountId) { return jdbcClient .sql("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_ACCOUNTID + " = :accountId") .param("accountId", accountId) .query(new UserMapper()) .optional(); }
3. 使用JdbcClient的命名参数SQL构建API
直接在方法内用命名参数编写SQL,配合参数绑定,这种方式完全符合安全规范,IntelliJ不会触发提示:
public Optional<User> getUserByAccountId(String accountId) { return jdbcClient .sql("SELECT * FROM USERS WHERE ACCOUNTID = :accountId") .param("accountId", accountId) .query(new UserMapper()) .optional(); }
4. 手动添加IntelliJ注释跳过检查
如果必须保留原有拼接方式,可以添加IntelliJ专属注释,强制跳过该SQL的安全检测:
public Optional<User> getUserByAccountId(String accountId) { return jdbcClient //noinspection SqlSourceToSinkFlow .sql(UserSql.SELECT_BY_ACCOUNTID) .query(new UserMapper()) .param(accountId) .optional(); }
原因说明
IntelliJ的SQL注入检测无法识别编译期静态字符串拼接的安全性,它默认认为所有动态拼接的SQL都存在注入风险,哪怕拼接的是固定常量。上述方法要么让SQL成为可直接解析的静态文本,要么用框架提供的安全标识类,要么手动告知IDE该SQL是安全的。
内容的提问来源于stack exchange,提问作者Joshua Swink
相关产品推荐
相关产品推荐

