微信公众号:51 码农网
专业编程问答社区
www.51manong.com
1. 先看 #{}解析为一个 JDBC 预编译语句(prepared statement)的参数标记符, 把参数部分用占位符 ? 代替。动态解析为:
select * from t_user where username = ?;
而传入的参数将会经过 PreparedStatement 方法的强制类型检查和安全检查等处理,最后作为一个合法的字符串传入。
在 #{}预处理之后可以预防 SQL 注入传入 username 为 a‘or’1=1,使用 #{}, 经过 sql 动态解析和预编译, 会把单引号转义为’那么 sql 最终解析为:
select * from t_user where username = "a\' or \'1=1";
2. 再看 ${}这种方式只会做简单的字符串替换,在动态 SQL 解析阶段将会进行变量替换, 假如传递的参数为 51mn, 最终处理结果如下:
select * from t_user where username = '51mn' ;
${} 预编译之前就已经被替换, 有被注入的风险。如果传入的 username 为 a‘or’1=1, 那么使用 ${} 处理后直接替换字符串的 sql 就解析为:
select * from t_user where username = 'a' or '1=1' ;
所有的用户信息都会被查询出来了。