JAVA简单教程:数据库操作(三)——PreparedStatement和动态SQL

如果我们的SQL语句是固定的,但是参数会不断变化,那我们要怎么办呢?

首先看看以下的处理方式:

statement.executeQuery("select * from user where userid = "+userInputId);


看起来我们是解决了我们的需要,但是其实这种写法会带来很严重的问题。

加入我们的userInputId是[b]1 or 1=1[/b],那么上面的SQL就会编程:
select * from user where userid = 1 or 1=1

这样,无论userid 为多少,我们都会返回所有用户记录。

这种动态SQL会造成我们著名的SQL注入(SQL Injection)的安全漏洞。这种漏洞除了可以窃取你的数据库记录外,严重的时候更能够破坏你的数据库结构,让你的数据库彻底毁掉。例如:

statement.execute("insert int user values(......"+userInput+")");

如果userInput是:
null);delete from user;--
那么,就会执行两条SQL命令,第一条就是创建一个user记录,第二条就会把所有user记录删掉!!

为了解决这种参数会变化但是SQL结构固定的动态SQL语句,jdbc提供了PreparedStatment这种操作方式:


java.sql.PreparedStatement ps = conn.preparedStatement("select * from user where userid = ?");

...

ps.setInt(1,userInputId);
ResultSet rs = ps.executeQuery();
...


这个接口会自动把一些非法字符串进行转换,防止用户串改操作语句。

而且使用PreparedStatement还有利于提高数据库效率,对于数据库,执行以下的两条SQL:
select * from user where userid = 1
select * from user where userid = 2
它会视为两条不同的SQL来执行,并且把执行过程分别存储起来,但是对于preparedStatement,它会记录:
select * from user where userid = ?
每次会根据参数返回操作结果,无论执行多少次都只会保留一份操作副本,能够有效节省数据库的编译SQL性能。

但是PreparedStatement也不是万能,假如我们的变化不是限制在参数上,就有问题,例如我们获取的数据表可能是动态的,或者where条件是动态的。那么我们怎么来处理这种情况并且有效防止SQL Injection呢?
很简单,但是却比较麻烦,就是限制用户的输入,并且不要直接把用户输入直接作为SQL凭借部分。

应用实例:
根据用户输入读取不同数据表的所有信息,要求:
用户输入:user时,获取所有用户表信息(user表)
用户输入:org时,获取所有组织信息(org表)
用户输入其它信息:返回所有新闻记录(news表)

实现:

String sql = "select * from news";
if(userInput != null && userInput.equalsIgnoreCase("user"))
sql = "select * from user";
if(userInput != null && userInput.equalsIgnoreCase("org"))
sql = "select * from org";


利用这种方法和PreparedStatement就能够有效防止SQL注入。

无论日后是否使用ORM工具来操作数据库,都必须小心不要造成SQL注入漏洞,否则后果不堪设想。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值