注入攻击,就是在sql语句传入数据值时做的引号修改
例:"select * from activity where userName = '+username+' and pwd = '+pwd+'"
在传入pwd的值时,传入 123’ or ‘a’ = 'a
这里就改变了sql语句原本的结构了,sql语句变成了
例:"select * from activity where userName = 'XXX' and pwd = '**123’ or 'a' = 'a**'"
所以这里查询是必定成功的。
原因:sql语句使用的是字符串拼接。
防注入:使用PreparedStatement接口
PrepareStatement在未传参时便使用connection.prepareStatement(sql)传入sql语句,也就是sql语句进行的作用在这个时候已经进行分析、编译了,也就是预编译,它会在单引号前面加转义字符"",因此单引号也被当成传入的数据,如上面传入的123’ or ‘a’ = 'a在此时只会当成sql语句中的一个参数值,or也不会再另外其作用了。
package com.msb.test1;
import java.sql.*;
public class TestJDBC4 {
private static String driver = "com.mysql.cj.jdbc.Driver";
private static String url = "jdbc:mysql://127.0.0.1:3306/green?UseSSL=false&&useUnicode=true&&charecterEncoding=UTF-8&ServerTimezone=Asia/shanghai";
private static String user = "root";
private static String password = "root";
public static void main(String[] args){
testQuery();
}
//查询
public static void testQuery(){
Statement statement = null;
Connection connection = null;
ResultSet resultSet = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
String sql = "select * from activity where ativity_id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql); //获取语句对象
preparedStatement.setInt(1,1); //setXxx(问号的编号,数据)
//传入参数后再执行CURD,不需要再传入sql语句
resultSet = preparedStatement.getResultSet();
while (resultSet.next()){ //下一行有值则返回true,可用于遍历获取数据库查询出来每一行的值
int id = resultSet.getInt("activity_id");
int theId = resultSet.getInt(1);
String userAccount = resultSet.getString("user_account");
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(null != resultSet){
try {
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(null != statement) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != connection){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}