JDBC中Statement的Sql注入问题详解

 更新时间:2023年10月16日 11:30:32   作者:发光吖  
这篇文章主要介绍了JDBC中Statement的Sql注入问题详解,sql注入攻击指的是通过构建特殊的输入作为参数传入web应用程序,而这些输入大都是sql语法里的一些组合,通过执行sql语句进而执行攻击者所要做的操作,需要的朋友可以参考下

Statement的Sql注入问题

sql注入攻击指的是通过构建特殊的输入作为参数传入web应用程序,而这些输入大都是sql语法里的一些组合,通过执行sql语句进而执行攻击者所要做的操作,其产生的主要原因在于应用程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

我们通过一个用户登录的小案例来大致了解sql注入的情况:(Oracle数据库环境)

首先准备一张表t_user:

在这里插入图片描述

create table t_user(
	name varchar2(10) primary key,
	password varchar2(10) not null
)

插入一些测试数据:

insert into t_user(name,password) values('tom','123');
insert into t_user(name,password) values('mary','456');
commit;

所使用的数据库驱动:ojdbc8.jar

用JDBC连接数据库,写一个登录案例:

public class TestSqlInjection {
	public static void main(String[] args) {
		String driverClass = "oracle.jdbc.OracleDriver";
		String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
		String user = "briup";
		String password = "briup";

		@SuppressWarnings("resource")
		Scanner input = new Scanner(System.in);
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName(driverClass);
			conn = DriverManager.getConnection(url, user, password);
			stmt = conn.createStatement();
			System.out.println("请输入用户名:");
			String uname = input.nextLine();
			System.out.println("请输入密码:");
			String upass = input.nextLine();
			String sql = "SELECT name,password FROM t_user WHERE name='" + uname + "' AND password='" + upass + "'";
			// uname xxx
			// upass xxx' or '1'='1
			rs = stmt.executeQuery(sql);
			if (rs.next()) {
				System.out.println("登录成功");
				// 这时候我们认为用户名和密码都正确情况下查询出来的用户肯定只有一条
				System.out.println("欢迎您," + uname);
			} else {
				System.err.println("用户名或密码错误!");
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

效果:

在这里插入图片描述

很显然使用Statement的确产生了sql注入的问题。

但是使用PreparedStatement可以有效解决这个问题。

public class TestSqlInjection {
	public static void main(String[] args) {
		String driverClass = "oracle.jdbc.OracleDriver";
		String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
		String user = "briup";
		String password = "briup";

		@SuppressWarnings("resource")
		Scanner input = new Scanner(System.in);
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			Class.forName(driverClass);
			conn = DriverManager.getConnection(url, user, password);
			String sql = "SELECT name,password FROM t_user WHERE name=? AND password=?";
			ps = conn.prepareStatement(sql);
	        //uname xxx
	        //upass xxx' or '1'='1
			System.out.println("请输入用户名:");
			String uname = input.nextLine();
			ps.setString(1, uname);
			System.out.println("请输入密码:");
			String upass = input.nextLine();
			ps.setString(2, upass);
			rs = ps.executeQuery();
			if (rs.next()) {
				System.out.println("登录成功");
				System.out.println("欢迎您," + uname);
			} else {
				System.err.println("用户名或密码错误!");
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

PreparedStatement 除了可以防止sql注入,在执行大量重复性插入语句时,也会明显提升程序运行的性能,同时避免了繁琐的字符串拼接操作。

对比:

Statement ,是每次执行一个sql语句,就要把一个完成的sql语句发送给数据库进行执行,然后取回返回的结果。

PreparedStatement ,可以把一个sql语句的结构,提前发送给数据库进行预处理,然后在专门给发送要操作的具体的值,在数据量大的时候,这种方式会大大提高执行效率。

到此这篇关于JDBC中Statement的Sql注入问题详解的文章就介绍到这了,更多相关Statement的Sql注入问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RabbitMQ排他性队列Exclusive Queue详解

    RabbitMQ排他性队列Exclusive Queue详解

    这篇文章主要介绍了RabbitMQ排他性队列Exclusive Queue详解,如果你想创建一个只有自己可见的队列,即不允许其它用户访问,RabbitMQ允许你将一个Queue声明成为排他性的Exclusive Queue,需要的朋友可以参考下
    2023-08-08
  • Spring Boot+Aop记录用户操作日志实战记录

    Spring Boot+Aop记录用户操作日志实战记录

    在Spring框架中使用AOP配合自定义注解可以方便的实现用户操作的监控,下面这篇文章主要给大家介绍了关于Spring Boot+Aop记录用户操作日志实战的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • Java BufferedReader相关源码实例分析

    Java BufferedReader相关源码实例分析

    这篇文章主要介绍了Java BufferedReader相关源码实例分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 一文掌握Spring Cookie和Session 是什么及区别介绍

    一文掌握Spring Cookie和Session 是什么及区别介绍

    Cookie和Session都是用于在客户端和服务器之间传递信息的技术,但它们的工作方式和使用场景有所不同,Cookie是在客户端保存用户信息的一种机制,而Session是在服务器端保存用户信息的一种机制,本文介绍Spring Cookie和Session 是什么,感兴趣的朋友一起看看吧
    2025-01-01
  • Java前端Layer.open.btn验证无效解决方法

    Java前端Layer.open.btn验证无效解决方法

    在本篇文章里我们给大家整理了一篇关于Java前端Layer.open.btn验证无效解决方法以及实例代码,需要的朋友们可以参考学习下。
    2019-09-09
  • 详解Java的内存模型

    详解Java的内存模型

    本文更准确的说法应该是JVM的内存模型,但是这里又牵扯了一些其他的前置知识,主要是想从Java入手,从源头上梳理一遍整个Java底层运行的机制,中间会额外补充一些和题目无关的前置基础,导致主讲内存模型的篇幅所占的比例就不是那么绝对。
    2021-06-06
  • javafx实现图片3D翻转效果方法实例

    javafx实现图片3D翻转效果方法实例

    程序实现思路: 在javafx中Node对象有一个effect属性,可以用于实现各种特效。PerspectiveTransform特效可以使Node对象实现透视变换。因此我们可以通过计算透视变换中每个点的位置来实现3D翻转特效。
    2013-04-04
  • Java的三种代理模式简述

    Java的三种代理模式简述

    这篇文章主要简述Java的三种代理模式,java的代理模式主要包括静态代理、动态代理、Cglib代理,感兴趣的小伙伴可以参考下面文章的具体内容
    2021-09-09
  • Spring Boot Admin Server管理客户端过程详解

    Spring Boot Admin Server管理客户端过程详解

    这篇文章主要介绍了Spring Boot Admin Server管理客户端过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 最新IntelliJ IDEA 2020版本的安装教程详解

    最新IntelliJ IDEA 2020版本的安装教程详解

    这篇文章主要介绍了最新IntelliJ IDEA 2020版本的安装教程详解,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08

最新评论