博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaWeb学习-JDBC系列-10-SQL注入问题和PreparedStatement对象
阅读量:4302 次
发布时间:2019-05-27

本文共 2677 字,大约阅读时间需要 8 分钟。

前面我们用JDBC模拟了一个用户登录的问题,看起来很棒,没有什么问题,是不是。其实,知道sql注入问题的人就会发现这个代码这样写是不对的,百分百引发sql注入问题。本篇来学习什么是SQL注入问题和如何解决这个问题。

1.什么是SQL注入问题

现在代码还是前面一篇的代码,我们再次运行Login.java这个main方法,看看下面我是如何输入的

请输入用户名:asdf请输入密码:asdf' or '1'='1欢迎回来,Lucy

这里我们明明输入了一个不存在的用户asdf,密码这个输入就有讲究,sql注入就出现在这里。这里看看我如何解释这个sql注入,为什么会打印 欢迎回来,Lucy.

先贴出我表的全部内容。

关键出问题代码

String sql = "SELECT * FROM student WHERE Name='"+ username +"' AND pwd='"+ password +"'";

在上面我们sql语句中使用了'变量名'的格式来表示这里有一个变量需要引用。这里我们用户名是asdf,密码是asdf' or '1'='1, 我们把这两个变量的值替代到sql语句中去,结果是这样的。

String sql = "SELECT * FROM student WHERE Name='asdf' AND pwd='asdf' or '1'='1'";

注意我密码为什么要写成asdf' or '1'='1,看起来前后都丢了一个单引号。没错,证书前后丢了单引号,导致上面这行sql语句其实变成了三个逻辑条件的语句:

String sql = "SELECT * FROM student WHERE Name='asdf' AND pwd='asdf' or '1'='1'";

上面三个表达式语句,前面两个查询的结果不存在。关键在于第三个表达式 or 表示或的逻辑关系,后面1=1这个肯定返回true,所以不管前面两个表达式结果返回false,加上了or后面的1=1,这个sql语句实际上返回结果是true。一旦返回为true,那么结果集对象rs就有next()方法,也就是这里查询的第一行数据,刚好我们表中第一行数据的用户名是Lucy,所以这个打印“欢迎回来,Lucy”, 就是这么来的。

这个过程就是SQL注入攻击,你看看随便输入一个用户名和密码,就查询到了我们数据表中的用户名这个信息。如果这个信息拿出来去做其他的分析和碰撞,黑客很可能拿到这个用户的密码。这样用户信息就泄露了,带来了安全问题。

 

2.使用PreparedStatement解决sql注入问题

既然这个sql注入问题大家都知道,那么肯定有解决办法。所以,这里学习一个新的对象PreparedStatement,看到这个对象名称,我们很容易想起Statement对象。没错,两个对象是有关系的,PreparedStatement是Statement的子类,而且PreparedStatement使用有下面特点:

1. 性能要比Statement高2. 会把SQL语句先编译3. SQL语句中的参数会发生变化,过滤掉用户输入的关键字,例如我们前面sql注入的or这个关键字

使用PreparedStatement修改DoLogin.java内容。

package com.anthony.login;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import com.anthony.utils.DBUtils;public class DoLogin {		public Student findUser(String username, String password) {		Connection conn = null;		PreparedStatement stmt = null;		ResultSet rs = null;		Student s = null;		try {			conn = DBUtils.getConnection();			String sql = "SELECT * FROM student WHERE Name=? AND pwd=?";			stmt = conn.prepareStatement(sql);			//给SQL中的?赋值,有几个?就要写几个设置语句。 ?在这里是占位符的作用			stmt.setString(1, username);			stmt.setString(2, password);			rs = stmt.executeQuery();						if(rs.next()) {				s = new Student();				s.setName(rs.getString("Name"));				s.setAge(rs.getInt("Age"));				s.setGender(rs.getString("Gender"));				s.setId(rs.getInt("ID"));				s.setPassword(rs.getString("pwd"));			}		} catch (Exception e) {			e.printStackTrace();		}		return s;	}}

上面注意这几行代码,看看我写的注释也就明白了,这里问号是占位符的作用,SQL语句提前进行了编译和过滤。

String sql = "SELECT * FROM student WHERE Name=? AND pwd=?";stmt = conn.prepareStatement(sql);//给SQL中的?赋值,有几个?就要写几个设置语句。 ?在这里是占位符的作用stmt.setString(1, username);stmt.setString(2, password);rs = stmt.executeQuery();

测试下效果

请输入用户名:asdf请输入密码:asdf' or '1'='1用户名或密码错误!

我们本来还是想利用前面的sql注入写法,结果却是不行,使用了PreparedStatement对象之后,sql先进行了编译和过滤关键字,所以用户还是老老实实去写正确用户名和密码,别耽误时间去找这个sql注入攻击的漏洞。

转载地址:http://duows.baihongyu.com/

你可能感兴趣的文章
量化策略回测DualThrust
查看>>
量化策略回测BoolC
查看>>
量化策略回测DCCV2
查看>>
mongodb查询优化
查看>>
五步git操作搞定Github中fork的项目与原作者同步
查看>>
git 删除远程分支
查看>>
删远端分支报错remote refs do not exist或git: refusing to delete the current branch解决方法
查看>>
python multiprocessing遇到Can’t pickle instancemethod问题
查看>>
APP真机测试及发布
查看>>
通知机制 (Notifications)
查看>>
10 Things You Need To Know About Cocoa Auto Layout
查看>>
C指针声明解读之左右法则
查看>>
一个异步网络请求的坑:关于NSURLConnection和NSRunLoopCommonModes
查看>>
iOS 如何放大按钮点击热区
查看>>
ios设备唯一标识获取策略
查看>>
获取推送通知的DeviceToken
查看>>
Could not find a storyboard named 'Main' in bundle NSBundle
查看>>
CocoaPods安装和使用教程
查看>>
Beginning Auto Layout Tutorial
查看>>
block使用小结、在arc中使用block、如何防止循环引用
查看>>