所谓 SQL 注入,就是通过把 SQL 命令插入到 Web 表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。
举一个例子来更好地理解,假设我们有一个登陆系统,我们需要通过输入的帐号以及密码来进行判断用户输入的信息是否是数据库中存在的数据而允许其是否通过
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String name = input.nextLine();
System.out.println("请输入密码");
String password = input.nextLine();
String sql = "select * from student where name='" + name + "' and password ='" + password + "'";
System.out.println(sql);
search(sql);//连接数据库执行查询操作
}
public static void search(String sql){
try {
//1、加载驱动
Class.forName(driver);
//2、建立连接
Connection connection = DriverManager.getConnection(url, username, password);
//3、生成专门执行sql的对象,statement
Statement statement = connection.createStatement();
//4、执行sql语句
ResultSet resultSet = statement.executeQuery(sql);
//5、处理查询结果集
if(resultSet.next()){
System.out.println("登陆成功");
}else {
System.out.println("登陆失败");
}
//6、释放资源
if (resultSet!=null) {
resultSet.close();
}
if (statement!=null) {
statement.close();
}
if (connection!=null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
显然,当我们输入的账号和密码正确是,我们一定会登陆成功,但是当我们将密码输入为’1‘ or ’1‘=’1‘,为无论账号是否正确,都会显示登陆成功,这是为什么呢,让我们看一下拼接而成的SQL语句
SELECT * FROM student WHERE name = 'lalala' AND password = '1' OR '1'='1';
这会使查询返回所有用户,因为 **1=1 总是为真**
- 为什么会发生SQL注入
- 首先,sql的执行流程大致如下:
- 本地sql语句拼接---->发送sql语句给DBMS(数据库管理系统)---->DMBS进行sql编译
- 造成sql注入的原因在于我们在本地拼接了一条"有安全隐患的"sql语句,之后我们将拼接好的sql语句发送给DBMS,DBMS将”有安全隐患”的sql语句进行了编译执行。
- 这里的重点是:用户的信息参与到了编译过程,而这个信息出现了问题
- 如何防范SQL注入问题
- 使用参数化查询或者预编译语句:使用参数化查询(Prepared Statements)可以有效防止 SQL 注入,因为它们在执行查询之前将输入数据与查询语句分离。
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,name);
statement.setString(2,password);