Ibatis自动解决sql注入机制

疑问1:为什么IBatis解决了大部分的sql注入?(实际上还有部分sql语句需要关心sql注入,比如like)

 

  之前写Java web,一直使用IBatis,从来没有考虑过sql注入;最近写php(新手),突然遇到一大堆sql注入问题,如sql语句:

SELECT * FROM message WHERE message_id =$id;

id通常允许输入数字或字符,如果用户输入了5' OR '1'='1,被执行的sql语句就变成了

SELECT * FROM message WHERE message_id = '5' OR '1'='1';

返回了整个库记录,更有甚者,用户输入5';DELETE FROM message WHERE message_id='10 被执行的sql变成了

SELECT * FROM message WHERE message_id = '5';DELETE FROM message WHERE message_id='10';

将有记录被直接删除,甚至危害整个数据库。在php开发中通常需要程序员写附加的代码保证,主要有三类方法:1)使用intval转换字符串为值;2)过滤关键字(不推荐);3)使用转义字符转义特殊字符(如单引号、双引号和百分号等),今天突然想到为什么Java web使用ibatis就不需要程序员来防止这些注入问题呢?

 

Ibatis执行sql步骤:      1)预编译

                                         2)替换占位符变量

                                         3)执行sql

对于sql语句:

SELECT * FROM message WHERE message_id =#id#;

id为map中的key或者message bean中的属性,在预编译过程后,sql语句变成

SELECT * FROM message WHERE message_id =?;

?是占位符,代表这个变量需要在执行前替换,在替换占位符的过程中,ibatis会将特殊字符转义为普通字符,如'变成\'、%变成\%,这样被注入的语句就变成          

SELECT * FROM message WHERE message_id = '5\' OR \'1\'=\'1';

执行结果还是原结果或者sql报错,不会出现被注入情况。

 

延伸:

       在ibatis中,有两种书写变量的方式:

       1)SELECT * FROM message WHERE message_id =#id#;

   2)SELECT * FROM message WHERE message_id =$id$;

第一种方式是加双引号并转义特殊字符的方式替换变量,第二种方式是直接替换变量。比如order by topicId , 语句这样写... order by #xxx# ibatis 就会把他翻译成order by 'topicId' (这样就会报错) 语句这样写... order by $xxx$ ibatis 就会把他翻译成order by topicId。

      

       看了网上的其它帖子,都讲到了name like '%$name$%' 这种用法需要用CONCAT('%',#param#,'%')来替换,这里就不再展开,只需要在写xml配置文件的时候注意就行。

       总结起来就是一句话,$符的字符串连接方式不安全,#符的加单引号并转义特殊字符的方式是安全的。

posted @ 2015-11-23 13:56  Mr.24点以后  阅读(932)  评论(0编辑  收藏  举报