SQL注入是一种比较常见的网路攻击方式,一些恶意人员在需要用户输入的地方,恶意输入SQL语句的片段,通过SQL语句,实现无账号登录,甚至篡改数据库。
在一个登录界面,要求用户输入账号和密码。
我们的代码中会有如下SQL语句:
String sql="select * from user where account='"+account+"' and password='"+password+"'";
账号:' or 1=1-- (--后面有一个空格)
密码:
当我们输入了这个账号和密码,那么SQL语句就变成:
String sql="select * from user where account='' or 1=1 -- ' and password=''";
这个查询条件就变成account=‘’ 或者1=1,这个条件是恒成立的。
后面的-- ,就是注释。
这样就可以实现免账号登录。
账号:';drop database test;-- (--后面有一个空格)
密码:
当我们输入了这个账号和密码,那么SQL语句就变成:
String sql="select * from user where account='';drop database test;-- ' and password=''";
这个查询条件就变成account=‘’ 或者1=1,这个条件是恒成立的。
后面的-- ,就是注释。
这样就能删除数据库。
使用PreparedStatement可以防止SQL注入。sql语句中的参数需要用?代替。PreparedStatement对sql预编译后,然后调用setXX()方法设置sql语句中的参数。这样再传入特殊值,也不会出现sql注入的问题了。
用户的账号信息:
create table user(
id int primary key auto_increment,
account varchar(20),
password varchar(20),
nickname varchar(20)
);
insert into user(account,password,nickname) values('Jack','123456','杰克');
insert into user(account,password,nickname) values('Mary','888888','玛丽');
select*from user;
创建一个javaweb项目。Login类实现登录功能,用Junit进行单元测试,创建LoginTest类实现登录测试功能。
Login.java
package net.jdbc.test;
import java.math.BigDecimal;
import java.sql.*;
public class Login {
//数据库url、用户名和密码
static final String DB_URL="jdbc:mysql://localhost:3306/test?";
static final String USER="root";
static final String PASS="root123";
public static void login(String account,String password) {
try {
//1、注册JDBC驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
//3、操作数据库
String sql="select * from user where account=? and password=?";
//获取操作数据库的对象
//用PreparedStatement可以预防SQL注入
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,account);//设置参数
preparedStatement.setString(2,password);
ResultSet resultSet = preparedStatement.executeQuery();//执行查询sql,获取结果集
if (resultSet.next()){ //遍历结果集,取出数据
String name = resultSet.getString("nickname");
//输出数据
System.out.println(name+"登录成功");
}else{
System.out.println("用户登录失败......");
}
//4、关闭结果集、数据库操作对象、数据库连接
resultSet.close();
preparedStatement.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch(SQLException e){
e.printStackTrace();
} catch(Exception e){
e.printStackTrace();
}
}
}
LoginTest.java
package net.jdbc.test;
import org.junit.Test;
import static org.junit.Assert.*;
public class LoginTest {
@Test
public void login() {
Login.login("' or 1=1-- ","");//SQL注入测试
Login.login("Jack","123");//正确账号,错误密码
Login.login("Jack","123456");
Login.login("Mary","888888");
}
}