Java应用防范SQL注入:PreparedStatement的setString防注入原理是什么
PreparedStatement防范SQL注入的核心原理
PreparedStatement本质是通过预编译+参数化赋值的机制从根源上避免SQL注入,具体实现逻辑分为两步:
预编译阶段锁定SQL结构
调用con.prepareStatement("select * from users where userId=?")时,这条带占位符?的SQL会提前提交到数据库端完成语法解析、执行计划生成,整个SQL的结构此时就已经完全固定:查询的表为users,唯一查询条件是userId字段匹配某个值。后续无论给占位符传入什么内容,都只会被当做参数值处理,不会被解析为SQL语法的一部分,从根源上杜绝了恶意输入篡改SQL逻辑的可能。
而你举的SQL注入示例是直接拼接SQL字符串,拼接完成后才会提交给数据库解析,用户输入里的'、or等内容会被当做SQL语法的一部分执行,才会出现'1'='1恒成立返回全表数据的问题。
setString自动转义特殊字符
setString方法在给占位符赋值时,会自动对参数中的所有SQL特殊字符做转义处理,常见转义规则包括:
- 单引号
'转义为两个单引号'' - 反斜杠
\转义为\\ - 注释符
--、/*等会被当做普通字符串处理
比如你传入的userId为恶意值abcd' or '1'='1,经过setString处理后,最终传入数据库的参数会被转义为'abcd'' or ''1''=''1',数据库会把整段内容当做userId的匹配值检索,不会把or '1'='1解析为额外的查询条件,自然不会触发注入。
-- 最终实际执行的SQL等价于,仅会查询userId为`abcd' or '1'='1`的用户,不会返回全表数据 select * from users where userId = 'abcd'' or ''1''=''1'
内容的提问来源于stack exchange,提问作者Dwaipayan Goswami
相关产品推荐
相关产品推荐

