Java:PreparedStatement 防止SQL注入

Statement和PreparedStatement的区别

联系

  1. PreparedStatement继承自Statement,两者都是接口。
  2. Statement 用于执行静态SQL 语句在执行时,必须指定一个事先准备好的SQL语句。
  3. PreparedStatement 是预编译的SQL语句对象,sql语句被预编译并保存在对象中。被封装的sql语句代表某一类操作,语句可以包含动态的参数 “ ?”,执行时可以为“ ? ”动态设置参数值。
  4. 使用PreparedStatement对象执行sql时,sql语句被数据库进行解析和编译,然后被放到命令缓存区,每当执行同一个PreparedStatement 对象时,它就会被解析一次,但不会被再次编译。在缓存区可以发现预编译的sql命令,并且可以重用。
  5. PreparedStatement 可以减少编译次数提高数据库性能。

防止SQL注入

方法一:创建Statement对象

例如:

1.Class.forName(com.mysql.jdbc.Driver);//加载驱动
2.Connection conn=DriverManager.getConnection("jdbc:mysql//:....")//创建与某个数据库的连接
3.Statement stmt=conn.CreateStatement();//创建一个statementd对象
4.String id=01;
5.String sql="delete from table where id='"+id+"'";//构建SQL语句
6.stmt.executeUpdate(sql);//执行SQL语句

上面的这段代码的本意是想删除在数据库里删除 id=01 的记录,但是如果有人将 id 的内容改为 " 01 or 1=1" 时,数据库在接收到命令后,无论你输入是否存在都会执行,因为数据库会把 " or 1=1"当成判断条件,所以无论如何该语句都会执行。那么表中的任何记录都将被删除,后果会非常严重。

缺点:

  • 不能防止sql 注入,安全性低
  • 每次执行都需要重新编译sql语句,效率低下。

方法二:创建PreparedStatement对象

1.Class.forName(com.mysql.jdbc.Driver);//加载驱动
2.Connection conn=DriverManager.getConnection("jdbc:mysql//:....")//创建与某个数据库的连接
3.String sql="delete from table where id=?";//构建SQL语句,设置占位符
4.PreparedStatement ps=conn.PreparedStatement(sql);//创建PreparedStatement时传入sql语句,实现预编译
5.ps.setInt(1,"01");//设置sql语句的占位符的值,注意第一个参数为1
6.ps.executeUpdate();//执行SQL语句

为什么PreparedStatement能防止sql注入呢???

因为sql 语句是预编译的,而且语句中使用了占位符,规定了sql语句的结构。并且如果输入" 01 or 1=1"时,数据库会把" 01 or 1=1"当成值,而不是"1=1" 当成判断条件,所以能防止sql注入。

实际开发中,建议使用PreparedStatement访问数据库,因为它不仅能防止sql注入,安全性提高;而且是预编译的 ,不用每执行一次都需要重新编译SQL语句,效率高;另外,它执行语句得到的结果是离线的,连接关闭后,仍然可以访问结果集。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章