一、什么是SQL注入漏洞?
简单理解是利用现有程序, 通过构建包含SQL关键字的特殊输入作为参数传入Web应用程序,最终达到欺骗服务器执行恶意的SQL命令。
二、SQL注入漏洞举例
有这样一个用户登录场景:登录界面包括用户名和密码输入框,以及提交按钮。输入用户名和密码,提交。应用程序从输入框获取用户名和密码构建SQL语句,查询数据库是否存在对应的用户密码确定登录状态。
假设我们目前有一个正确的账户,账户名为jackie,密码为123456
当我们在页面输入框,输入账号为jakie、密码为123456。
正常情况下:
SQL注入两个例子:
三、SQL注入漏洞解决
3.1 出现SQL注入漏洞的根本原因
之前我们一直使用Statement对象执行SQl语句,在这种方法下,他人通过输入SQL关键字,使应用程序在进行SQL语句拼接时出现漏洞。
3.2 解决办法
我们将改用PreparedStatement对象执行SQL语句,这种方法下,SQL进行预编译,SQL语句格式固定,使用占位符‘?’代替输入参数。这种情况下无论客户输入什么我们都识别为普通字符串,而不会识别为SQL关键字。
3.3 示例代码
import jdbc.utils.JDBCUtils;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author created by jackie on 2020/4/21
* @description: 利用PreparedStatement替代 Statemnet对象避免 SQL注入漏洞
*/
public class loopholeDemo {
@Test
public void test(){
boolean loginRestult = login("aaa","1234");
if(true == loginRestult){
System.out.println("登录成功");
} else{
System.out.println("登录失败");
}
}
public static boolean login(String username,String password)
{
Connection conn = null ;
PreparedStatement pstmt = null ;
ResultSet rs = null;
boolean flag =false ;
try {
//获得连接;
conn = JDBCUtils.getConnection();
//编写SQL,规定SQL语句格式,用占位符?代表输入参数
String sql = "select *from jdbc where username = ? and password =?";
//预处理SQL
pstmt =conn.prepareStatement(sql);
//设置参数
pstmt.setString(1,username);//替换上述sql第一个占位符‘?’
pstmt.setString(2,password);//替换上述sql第二个占位符‘?’
//执行sql
rs =pstmt.executeQuery();
if(((ResultSet) rs).next()){
flag =true ;
}else{
flag = false ;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn,pstmt,rs);
}
return flag ;
}
}