不使用Statement的原因:
我们在使用Statement接口时有一个缺点。因为在使用Statement接口要进行sql语句的拼接,这样做不仅麻烦,容易出错,而且还存在安全漏洞。就是我们在不知道正确的用户名或者密码的时候,在后面加上or 1=1 也可以获取正确的数据,这就是典型的sql注入。
如果使用Statement对象在执行SQL语句很容易受到SQL的注入,那什么是SQL注入呢?
所谓SQL注入就是用户在能够控制SQL查询、更新、插入、删除等语句的参数的情况下,攻击者通过构造特殊的输入字符串使后端程序错误地识别SQL查询语句中 ·的代码与数据部分从而导致数据库管理系统输出了非预期的结果的一种行为。
SELECT * FROM Users WHERE Username='1' OR '1'='1' AND Password='1'OR '1'='1'
可以通过这样的SQL语句注入直接不需要输入正确的语句,就可以获取用户登录成功的正确账号信息等访问!
sql注入示例:
![](https://img-blog.csdnimg.cn/img_convert/07067871ce867ee8b3fdd59b25d8122b.png)
假设参数值是通过GET方法传递到服务器的,且域名为www.example.com 那么我们的访问请求就是:
http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1
对上面的SQL语句作简单分析后我们就知道由于该语句永远为真,所以肯定会返回一些数据,在这种情况下实际上并未验证用户名和密码,并且在某些系统中,用户表的第一行记录是管理员,那这样造成的后果则更为严重。而PrepareStatement接口就不存在这个问题。因为PrepareStatement使用的是预编译语句,传入的任何数据都不会和已经预编译的sql语句进行拼接,避免了sql注入攻击。
那么PrepareStatement比Statement好在哪呢?
①提高了代码的可读性和可维护性。虽然使用PreparedStatement来替代Statement会多几行代码,但是避免了繁琐麻烦又容易出错的sql语句拼接,提高了代码的可读性和可维护性。
②提高了sql语句执行的性能。创建Statement对象时不使用sql语句做参数,不会解析和编译sql语句,每次调用方法执行sql语句时都要进行sql语句解析和编译操作,即操作相同仅仅是数据不同。而PrepareStatement就不会,因为每次创建PrepareStatement对象时使用sql语句做参数,会解析和编译该sql语句。也可以使用带有占位符的sql语句做参数,在通过setXxx()方法给占位符赋值后执行sql语句时无需在解析和编译sql语句,直接执行即可。多次执行相同的操作可以大大提高性能。
③提高了安全性。因为PrepareStatement使用的是预编译语句,传入的任何数据都不会和已经预编译的sql语句进行拼接,避免了sql注入攻击。
![](https://img-blog.csdnimg.cn/img_convert/e9d78da0a7301d3b5c2df1243cbc6fdb.png)