SQL注入问题

一、什么是sql注入

public class TestSql {
	
    public static void main(String[] args) {
		Scanner inScanner = new Scanner(System.in);
		System.out.println("请输入用户名");
		String username = inScanner.nextLine();
		System.out.println("请输入密码");
		String password = inScanner.nextLine();
		String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
		search(sql);
	}

	public static void search(String sql) {
		try {
			Class.forName("com.mysql.jdbc.Driver"); // 1.加载驱动
			//2.建立连接
			Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/login?useUnicode=true&characterEncoding=utf-8", "root", "");
			//3.创建执行的SQL语句
				
			Statement statement = (Statement) connection.createStatement();
			//4.执行sql语句
			ResultSet re = (ResultSet) statement.executeQuery(sql);
			//5.处理结果
			if(re.next()) {
				System.out.println("查询成功...");
			}else {
				System.out.println("查询失败...");
			}
	                 //6.释放资源
			if(re!=null) {
				re.close();
			}
			if(statement !=null) {
				statement.close();
			}
			if (connection !=null) {
				connection.close();
			}
				
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("找不到驱动类,加载失败");
			e.printStackTrace();
		} 
	}
	
}

以上的程序我们经过测试没什么问题,但是当输入如下数据的时候,一个可怕的问题出现了。

 

数据库中只有一个数据

那么为什么会产生这个现象呢?

我们将拼接好的sql语句拿出来

select * from user where username =' 111' and password = '1' or '1'='1';

我们将SQL语句拿到Navicat运行一下 

        这种通过传参就能改变SQL语句原本规则的操作就是SQL注入,这个在实际开发中当然是危险的,攻击者可以把SQL命令插入到Web表单的输入域或页面请求的查询字符串中,欺骗服务器执行恶意的SQL命令。

二、为什么会产生sql注入问题呢?

        我们可以把sql语句的执行流程大致分为一下几个步骤:

1.本地sql语句拼接

2.发送sql语句给DBMS

3.DBMS进行sql编译

        造成sql注入的原因在于我们在本地拼接了一条“有安全隐患的”sql语句。之后我们将拼接好的sql语句发送给DBMS,DBMS将“有安全隐患”的sql语句进行了编译执行。

这里的重点是:用户的信息参与到了编译过程,而这个信息出现了问题

三、如何解决sql注入问题呢?

        其实解决方法很简单:只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。

要想让用户的信息不参与SQL语句的编译,那么就需要预先对sql语句的框架进行编译,然后再给给sql赋值。预编译完成之后我们的DBMS只需要执行我们的sql语句,没必要再次编译。可以使用java.sql.PreparedStatement接口完成预编译,PreparedStatement是属于预编译的数据库操作对象

使用PreparedStatement需要注意的几点

①:占位符

String sql = "select * from user where username = ? and password = ?";

我们拼写好的sql语句不在使用直接拼接赋值的方式,而是采用 ? 占位符进行代替

②:创建方式

statement.setString(1, usernanme);
statement.setString(2, password);

总体代码如下

public class TestSql {
	
	public static void main(String[] args) {
		Scanner inScanner = new Scanner(System.in);
		System.out.println("请输入用户名");
		String username = inScanner.nextLine();
		System.out.println("请输入密码");
		String password = inScanner.nextLine();
		String sql = "select * from user where username = ? and password = ?";
		search(sql,username,password);
	}

	public static void search(String sql,String usernanme,String password) {
		try {
			Class.forName("com.mysql.jdbc.Driver"); // 1.加载驱动
			//2.建立连接
			Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/login?useUnicode=true&characterEncoding=utf-8", "root", "2020");
			//3.创建执行的SQL语句
			 PreparedStatement statement = (PreparedStatement) connection.prepareStatement(sql);
			// 给占位符赋值
			 statement.setString(1, usernanme);
			 statement.setString(2, password);
			
			//4.执行sql语句
			ResultSet re = (ResultSet) statement.executeQuery();
			//5.处理结果
			if(re.next()) {
				System.out.println("查询成功...");
			}else {
				System.out.println("查询失败...");
			}
	                //6.释放资源
			if(re!=null) {
				re.close();
			}
			if(statement !=null) {
				statement.close();
			}
			if (connection !=null) {
				connection.close();
			}
				
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("找不到驱动类,加载失败");
			e.printStackTrace();
		} 
	}
	
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值