SQL注入可以理解为通过添加恶意字段使得程序传入的SQL语句的语义发生改变,例如在登录账号并输入用户名之后添加注释符,使得后续的SQL语句失效,无需验证密码就可以进入系统;又或者在查询数据时添加or '1'='1'语句,可以获取数据库中的所有信息。
这种情况主要是因为查找功能采用的是字符串拼接方法,使得前台传入的参数直接拼接到SQL语句中,然后通过statement直接执行该SQL语句,即使存在恶意字段,它也无法检测出来。
//字符串拼接方法 public int selectByName(String name) throws SQLException { String sql = "SELECT * FROM test WHERE `name`='" + name + "'"; System.out.println(sql); Statement statement = connection.createStatement(); statement.executeQuery(sql); ResultSet resultSet = statement.getResultSet(); int count=0; while (resultSet.next()){ count++; } statement.close(); return count; //返回结果个数 }通过使用prepareStatement语句实现参数化查询,因为prepareStatement采用预编译机制,在创建prepareStatement对象时即导入了SQL语句进行预编译,此时SQL语句的参数用?代替;然后调用类似setString的方法传入参数,导致特殊字符被转义,从而使恶意字段失效。(转义的过程发生在MySQL驱动中)
//参数化查询 public int selectByName2(String name) throws SQLException { String sql = "SELECT * FROM test WHERE `name`=?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1,name); System.out.println(statement); statement.executeQuery(); ResultSet resultSet = statement.getResultSet(); int count=0; while (resultSet.next()){ count++; } statement.close(); return count; //返回结果个数 }(前两条语句均使用的是字符串拼接方法,第三条语句采用参数化查询)
即把恶意字段 B 作为字符串添加到参数中,而不是作为SQL语句中的独立字段。