温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

动态SQL怎样防止注入

发布时间:2026-09-29 12:52:34 来源:亿速云 阅读:97 作者:小樊 栏目:数据库

动态 SQL 防止注入的核心原则是:永远不要把用户输入直接拼接到 SQL 语句中。下面从原理到实践系统说明。


一、什么是 SQL 注入

动态 SQL 如果这样写:

"SELECT * FROM user WHERE name = '" + userName + "'"

用户输入:

' OR '1'='1

最终 SQL 变成:

SELECT * FROM user WHERE name = '' OR '1'='1'

就会绕过条件,造成注入。


二、最推荐的方式:使用「预编译(参数化)」✅

1. JDBC(Java)

String sql = "SELECT * FROM user WHERE name = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, userName);

✅ 参数永远被视为“数据”,不会被当作 SQL 执行


2. MyBatis

正确写法(推荐)

<select id="getUser">
  SELECT * FROM user
  WHERE name = #{name}
</select>

#{} → 预编译参数(安全)

错误写法(危险)

WHERE name = '${name}'

${} → 字符串拼接(极易注入)


3. MyBatis-Plus / JPA

QueryWrapper<User> qw = new QueryWrapper<>();
qw.eq("name", userName);

底层使用参数化,安全。


三、如果必须使用动态 SQL(如动态表名、排序)

1. 白名单校验(最安全)

List<String> allowed = Arrays.asList("id", "name", "create_time");
if (!allowed.contains(sortField)) {
    throw new IllegalArgumentException("非法字段");
}
ORDER BY ${safeField}

2. 枚举 / 映射表

Map<String, String> map = Map.of("时间", "create_time");
String column = map.get(input);

3. 严格类型校验

  • 数字:Integer.parseInt()
  • 布尔:true/false
  • 日期:DateTimeFormatter

四、其他防护手段(辅助,不是主力)

手段 说明
输入校验 长度、格式、正则
最小权限 DB 账号只给必要权限
WAF 网络层防护
关闭错误回显 防止信息泄露

⚠️ 这些不能替代参数化


五、总结一句话

动态 SQL 防注入 = 参数化优先 + 动态结构用白名单

如果你用的是 MyBatis / JPA / 某种具体框架,我可以给你更针对性的写法。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手