什么是SQL注入?
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
我们来模拟SQL注入:
数据表STU包含两个数据项STU(user,password)
Java:
只有当user(用户名)和password(都对应时才可以登录成功)
当用拼串的方式进行操作时:(有关拼串的代码上篇博客)
SQL语句编写:
String sql = “select * from STU where “;
sql = sql + “username=’”+ user +”’ AND password=’” + password + “’”;
- 情况1(账号密码正确)
String user = “tom”;
String password = “123321”;
登录成功
- 情况2(账号密码不对应情况1)
String user = “tom1”;
String password = “123321”;
登录失败,到这儿还一切正常但是
- 情况3(账号密码不对应)
String user = "a ’ OR password = “;
String password = " OR ‘1’ = '1”;
在账号密码不对应的情况下,完成了登录。
我们将SQL语句拿出来
select *
from STU
where username=‘a ’ OR password = ’ AND password=’ OR ‘1’ = ‘1’
条件判断语句被分成了三个部分
- username = ‘a’
- password = ‘AND password=’
- ‘1’=‘1’
显然最后’1’='1’必然成立,这就是SQL注入
如何解决SQL注入?
用PreparedStatement处理SQL语句即可
SQL语句编写:
String sql = “Select * from STU where username=? AND password=?”;
- 情况一(用户名密码对应)
String user = “tom”;
String password = “123321”;
- 情况二:(用户名密码不对应1)
String user = “tom1”;
String password = “123321”;
- 情况三(用户名和密码不对应2)
String user = "a ’ OR password = “;
String password = " OR ‘1’ = '1”;
有效的防止了SQL注入
相关代码:
public class SQLInject {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
conn = JDBCTools.getConnection();
stmt = conn.createStatement();
//能被SQL注入
// String sql = "select * from STU where ";
// //Sql注入
// JDBCTools.inject(sql);
String sql = "Select * from STU where username=? AND password=?";
JDBCTools.inject2(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.closeResource(conn, stmt, null);
}
}
}
拼串语句SQL注入:
public static void inject(String sql) {
Connection conn = null;
Statement stms = null;
ResultSet res = null;
try {
conn = JDBCTools.getConnection();
//SQL注入
String user = "a ' OR password = ";
String password = " OR '1' = '1";
//正常登录
// String user = "tom1";
// String password = "123321";
sql = sql + "username='"+ user +"' AND password='" + password + "'";
System.out.println(sql);
stms = conn.createStatement();
res = stms.executeQuery(sql);
if(res.next()) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.closeResource(conn, stms, null);
}
}
PreparedStatement语句防止SQL注入:
public static void inject2(String sql) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet res = null;
try {
conn = JDBCTools.getConnection();
//SQL注入
String user = "a ' OR password = ";
String password = " OR '1' = '1";
//正常登录
// String user = "tom1";
// String password = "123321";
ps = conn.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, password);
System.out.println(sql);
res = ps.executeQuery();
if(res.next()) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.closeResource(conn, ps, null);
}
}