今天是刘小爱自学Java的第67天。
感谢你的观看,谢谢你。
话不多说,开始今天的学习:
在某技术论坛上曾流传过一张图片。
这张图片只有程序员能看懂。
其他人看到都是一脸懵逼,而程序员看到则是会心一笑。
图片如下:
这其中就牵扯到数据库里的一个知识点:sql注入
以一个登录案例来说明这个知识点。
一、登录案例
我们用的很多软件,都有一个用户名和密码,用户的很多数据都是被存在该软件服务器里面的。
用户登录时需要保证用户名和密码正确才能登录成功。
好,现在我们来模拟这一场景。
用sql语句创建一个用户信息表,然后添加数据,这也算是对前几天知识点的一个复习:
当然现实里的用户信息肯定不是我们自己在数据库中创建的。这边仅仅只是为了演示方便。
现在要模拟用户登录的案例,业务逻辑如下:
用户名是唯一的。
用户登录要保证用户名和密码都要正确,缺一不可。
查询数据库中同时满足该用户名和密码的数据数量。
如果数量为1,登录成功并提醒用户。
否则登录失败并提示用户检查用户名和密码。
现在编写代码:
获取连接、创建执行语句对象
利用我们昨天封装的jdbc工具类,直接获取连接。
同时创建执行语句对象。
编写sql语句并执行
sql语句在Java中是以一个字符串的形式而编写的。
所以要将其意义完成转换。
同时因为name和pwd是两个变量,要将其拼接起来。
在Java中写sql语句的时候,可以先在数据库中编写好并执行看看有没有问题。
若是没有问题,再将其拼接成对应的Java字符串。
处理结果
我们查询的是满足条件的数据数量,也就是count(*)
调用getInt(count(*))方法可以得到满足条件的数据数量,根据业务逻辑:如果为1,登录成功;否则登录失败。
二、登录测试以及SQL注入
好,代码编写完成,我们做个测试。
用户名密码表中存在
所以登录成功。
密码1234是不正确的
所以登录失败。
那么,现在问题来了。
看中密码1234是不正确的,为何登录成功了呢?
猫腻就出现在用户名上,这个用户名叫“liuxiaoai'--”。
将用户名密码带入Java字符串中,再转换成sql语句。
“--”在sql中是注释,将后面的语句给注释掉了。
等于是只要保证前面的用户名正确,后面密码是啥都无所谓,不写都行。
所以回到一开始的图片,那张车牌号做了类似的事情:
车牌号
也就是类似于用户名的存在。
DROP DATABASE TABLICE
这是在一件什么事情?在删除数据库。
也是用的sql中的“--”,将后面的数据都注释掉了。
也就是说,摄像头拍到了这辆车,会记下其车牌号登录,同时删除自己的数据库。
这样的一种行为就是sql注入。
简单地理解也就是:
用户在提交数据时人为地添加一些特殊字符,使得sql语句的结构发生了变化。
最终可以在没有用户名或者密码的情况下进行登录,同时也可以完成恶意攻击。
当然这张图片只是一个笑话啦。
首先你并不知道交通部门的数据库名叫啥。
其次交通部门也有程序员,肯定会想到防范措施。
最后这样做一旦被发现,是要被直接吊销驾照的。
那该如何防范呢?就是使用预编译。
三、预编译
预编译、顾名思义也就是预先编译,代码如下:
占位符
?是一个占位符,表示所在的位置是一个参数。
它有一个非常强大的作用在于,占位符里的参数,必然会是普通字符串。什么意思呢?
我们以前学过转义字符。
本来“--”在sql中是注释的意思,但是通过占位符将其转义成一个普通的字符了,不具有注释的作用了。
预编译
预编译等于是将sql语句提前了,先编译再设置参数。
以前执行sql语句是在调用executeQuery()方法时。
其中PreparedStatement是Statement的一个子接口。
prepared,也就是准备、预先的意思。
参数索引
setString()方法就是给占位符赋具体的值。
参数表示的是sql语句中“?”占位符的索引:
1表示的第一个问号是name;
2表示的是第二个问号表示的是pwd。
其中索引从左开始从1开始数起。
以上便是对sql注入以及其防范措施预编译的说明。
预编译能防范sql注入,效率还高,很是实用。
最后
谢谢你的观看。
如果可以的话,麻烦帮忙点个赞,谢谢你。
领取专属 10元无门槛券
私享最新 技术干货