先准备一个user表
插入两条数据
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAr(32),
PASSWORD VARCHAr(32)
);
INSERT INTO USER VALUES(NULL,'zhangsan','123'),(NULL,'lisi','abc');
使用JDBC操作数据库
注意连接数据库时,要把代码中的数据库名以及密码改成自己的
import java.sql.*;
import java.util.Scanner;
public class JDBCDemo4 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
Statement statement=null;
Connection con=null;
ResultSet rs=null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/db2?characterEncoding=utf8";
con= DriverManager.getConnection(url,"root","root");
statement=con.createStatement();
System.out.println("请输入用户名:");
String username=sc.nextLine();
System.out.println("请输入密码:");
String password=sc.nextLine();
String sql="select * from user where username='"+username+"' and password='"+password+"'";
rs=statement.executeQuery(sql);
if(rs.next()) // 有下一个就说明查询到数据了
System.out.println("登录成功!");
else
System.out.println("密码或用户名错误!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
// 释放资源
finally{
if(rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
这两个运行结果都没有问题
接下来请看看第三个运行示例结果:
这里输入的密码明显是错的,但是居然登录成功了 !!!
到底是为什么呢?
返回去看看sql查询语句
String sql="select * from user where username='"+username+"' and password='"+password+"'";
它是由字符串拼接而成的
所以第三张图的输入组成的sql查询语句为:
select * from user where username='zhangsan' and password='1' or 'a'='a'
问题出现在这里
or 'a'='a'
'a'='a'是一定成立的,并且使用了or连接,因此该条件不管什么时候都是成立的。
这里使用java的PreparedStatement解决该问题
import java.sql.*;
import java.util.Scanner;
public class JDBCDemo4 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
PreparedStatement ps=null;
Connection con=null;
ResultSet rs=null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/db2?characterEncoding=utf8";
con= DriverManager.getConnection(url,"root","root");
System.out.println("请输入用户名:");
String username=sc.nextLine();
System.out.println("请输入密码:");
String password=sc.nextLine();
String sql="select * from user where username=? and password=?";
ps=con.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
rs=ps.executeQuery();
if(rs.next()) // 有下一个就说明查询到数据了
System.out.println("登录成功!");
else
System.out.println("密码或用户名错误!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
// 释放资源
finally{
if(rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
修改代码后,再次运行:
到这里输入'1' or 'a'='a就会登录失败了。
PreparedStatement使用的是预编译方式,会把sql语句空缺部分使用'?'占位了,然后进行预编译,sql语句就不是通过字符串拼接得来的了,以此解决SQL注入问题。



