如何解决SQL注入
前言
SQL注入是指Web应用程序不对用户输入数据的合法性进行判断或者不进行严格的过滤。攻击者可以在 Web 应用程序中预定义查询。在语句末尾添加额外的SQL语句,实现在管理员不知情的情况下进行非法操作,从而欺骗数据库服务器执行未经授权的任意查询,从而进一步获取相应的数据信息。
1. SQL注入案例
模拟用户登录的SQL注入案例。用户在控制台输入用户名和密码,然后使用Statement字符串拼接来实现用户的登录。 。
1.1 首先创建用户表和数据数据库
-- 创建用户表 CREATE TABLE `users` (`id` INT(11) NOT NULL AUTO_INCRMENT, `username` VARCHAR(20) , `password` VARCHAR(50), PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;--插入数据 INSERT INTO users(username,`password`) VALUES('张飞','123321') ,('赵云','qazxsw'),('诸葛亮','123Qwe');INSERT INTO users(用户名,`密码`) VALUES('曹操','741258'),('刘备' ,'plmokn'),('孙权','!@#$%^');--查看数据SELECT * FROM users;
1.2 写入一个登录程序
package com.study .task0201;import java.sql.*;import java.util.Scanner;public class TestSQLIn { public static void main(String[] args) 抛出 ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver") ; String url = "jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=UTF-8";连接 conn = DriverManager.getConnection(url,"root","123456"); //系统.out.打印(康涅狄格州); // 获取状态ent执行平台对象Statement Statement smt = conn.createStatement();扫描仪 sc = 新扫描仪(System.in); System.out.println("请输入用户名:");字符串用户名 = sc.nextLine(); System.out.println("请输入您的密码:");字符串密码 = sc.nextLine(); String sql = "从用户中选择*,其中用户名 = '" + 用户名 + "' 和密码 = '" + 密码 +"'"; //打印出SQL System.out.println(sql); ResultSet resultSet = smt.executeQuery(sql); if(resultSet.next()){ System.out.println("登录成功!!!"); }else{ System.out.println("用户名或密码错误,请重新输入!!!"); } 结果集.close(); smt.close(); conn.close(); }}
1.3正常登录
输入正确的用户名和密码后,提示“登录成功”
p>
1.4 登录失败
当用户名或密码输入错误时,提示“用户名或密码错误,请重新输入”
<强>1.5模拟SQL注入
拼接的字符串中有or'1'='1',是常量条件,所以前面使用的是如果用户名和密码不存在,会检索到所有记录,所以提示“登录成功”
1.6 SQL语法错误
使用在拼接中方法中,也会出现SQL语法错误等错误,如
2.解决方案
使用Statement方法,可以实现字符串的拼接。改变原始SQL的真实含义会导致SQL注入的风险。要解决SQL注入,可以使用预处理对象PreparedStatement代替Statement进行处理。
2.1程序
导入java.sql.*;导入java.util.Scanner;public class TestSQLIn { public static void main(String[] args) 抛出 ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver");字符串 url = "jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=UTF -8"; Connection conn = DriverManager.getConnection(url,"root","123456"); //System.out.println(conn); // 获取语句执行平台对象 Statement // 语句 smt = conn .createStatement( ); Scanner sc= new Scanner(System.in); System.out.println("请输入用户名:"); String userName = sc.nextLine(); System.out.println("请输入密码:"); 字符串密码 = sc.nextLine(); 字符串 sql = "从用户中选择 *,其中用户名 = ?和密码=? "; // System.out.println(sql); // 结果集 resultSet = smt.executeQuery(sql);PreparedStatementprepareStatement = conn.prepareStatement(sql);preparedStatement.setString(1,userName);preparedStatement.setString(2, password); ResultSet resultSet = preparedStatement.executeQuery(); if(resultSet.next()){ System.out.println("登录成功!!!"); }else{ System.out.println("用户名或密码是错误,请重新输入!!!";); } preparedStatement.close(); resultSet.close(); // smt.close(); conn.close(); }}
2.2 正常登录
2.3 用户名和密码错误
当用户名或密码输入错误时,提示“用户名或密码错误,请重新输入”
2.4模拟SQL注入
根据之前的情况,编写SQL注入,经过测试,再次出现SQL注入。
2.5模拟SQL语法错误
之后使用预处理类,输入带单引号或双引号的内容也可以不再报SQL语法错误
3.总结
主要Statement和PreparedStatement的区别如下:
Statement用于执行静态SQL语句,执行时必须指定预准备的SQL语句
PrepareStatement是预编译的SQL语句对象.语句中可以包含动态参数“?”,可以通过“?”动态设置参数r值
PrepareStatement可以减少编译次数,提高数据库性能
以上是《如何解决SQL注入》一文的全部内容,谢谢你们大家都在读书!相信大家都有一定的了解,希望分享的内容对大家有所帮助。如果您想了解更多知识,请关注行业资讯频道!