JDBC2(防止sql注入,数据库连接池)

防止SQL注入

sql注入:利用sql语句的语法特点,应用层输入特殊格式,让原有的sql语句失效

创建表结构 并加入数据

create table login(
    lid int primary key auto_increment,
    lname varchar(20),
    lpwd varchar(20),
    lsex varchar(2),
    laddr varchar(50)
);
insert into login(lname,lpwd,lsex,laddr)
values('zhangsan','123456','男','西安北大街');

正常写法:

public static void main(String[] args) throws ClassNotFoundException, SQLException {
 
		Scanner input = new Scanner(System.in);
		// 1. 加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
 
		// 2. 获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myhomework03?serverTimezone=GMT",
				"root", "123456");
 
		System.out.println("请输入账号");
		String uname = input.next();
		System.out.println("请输入密码");
		String upwd = input.next();
 
		// 3.sql
		String sql = "select * from login where lname ='" + uname + "' and lpwd=' " + upwd + "'";
		Statement statement = conn.createStatement();// 不能防止sql注入
		ResultSet rs = statement.executeQuery(sql);
 
		// 4.执行sql语句
		if (rs.next()) {
			int lid = rs.getInt("lid");
			String lname = rs.getString("lname");
			String lpwd = rs.getString("lpwd");
			String lsex = rs.getString("lsex");
			String laddr = rs.getString("laddr");
			System.out.println(lid + lname + lpwd + lsex + laddr);
		} else {
			System.out.println("登录失败");
		}
	}

防止sql注入:

public static void main(String[] args) throws ClassNotFoundException, SQLException {
 
		Scanner input = new Scanner(System.in);
		// 1. 加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
 
		// 2. 获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myhomework03?serverTimezone=GMT",
				"root", "123456");
 
		System.out.println("请输入账号");
		String uname = input.next();
		System.out.println("请输入密码");
		String upwd = input.next();
 
//		// 3.sql
//		String sql = "select * from login where lname ='" + uname + "' and lpwd=' " + upwd + "'";
//		Statement statement = conn.createStatement();// 不能防止sql注入
//		ResultSet rs = statement.executeQuery(sql);
 
		// 防止sql注入 -- 利用sql语句的语法特点,应用层输入特殊格式,让原有的sql语句失效
		// 1.sql语句要变 -- 参数位置要使用 ?占位
		String sql = "select * from login where lname =? and lpwd =?";
		// 2. 执行对象要变 -- 预处理sql语句
		PreparedStatement prepareStatement = conn.prepareStatement(sql);
		// 3.给sql语句传参
		prepareStatement.setObject(1, uname);
		prepareStatement.setObject(2, upwd);
		ResultSet rs = prepareStatement.executeQuery();
		// 4.执行sql语句
		if (rs.next()) {
			int lid = rs.getInt("lid");
			String lname = rs.getString("lname");
			String lpwd = rs.getString("lpwd");
			String lsex = rs.getString("lsex");
			String laddr = rs.getString("laddr");
			System.out.println(lid + lname + lpwd + lsex + laddr);
		} else {
			System.out.println("登录失败");
		}
	}

使用PreparedStatement的优点:

  • 安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。
  • 语法不同:PreparedStatement可以使用预编译的sql,而Statment只能使用静态的sql
  • 效率不同:对于更改参数的同一SQL语句,PreparedStatement可以使用sql缓存区,效率比Statment高

数据库连接池

其实就是一个容器(集合),存放数据库连接的容器。

当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

优点:

    节约资源

    用户访问高效

实现:

  1. 标准接口:DataSource javax.sql包下的

    方法:
    

获取连接:getConnection()

归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接。

  1. 一般我们不去实现它,有数据库厂商来实现
  • C3P0:数据库连接池技术
  • Druid:数据库连接池实现技术,由阿里巴巴提供的

C3P0数据库连接池技术

  1. *导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,
    **** 不要忘记导入数据库驱动jar包

  1. 定义配置文件

名称: c3p0.properties 或者 c3p0-config.xml文件名称不可以修改

路径:直接将文件放在src目录下即可,路径不可修改

<c3p0-config>
	<!-- 使用默认的配置读取连接池对象 -->
	<default-config>
		<!-- 连接参数 -->
		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1/db6?serverTimezone=GMT
		</property>
		<property name="user">root</property>
		<property name="password">12345678</property>
		<!-- 连接池参数 -->
		<!-- 初始化连接数 -->
		<property name="initialPoolSize">5</property>
		<!-- 最大连接数 -->
		<property name="maxPoolSize">10</property>
		<!-- 超时时间:当连接池耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 
			0 -->
		<property name="checkoutTimeout">3000</property>
	</default-config>
	<named-config name="otherc3p0">
		<!-- 连接参数 -->
		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1/db5?serverTimezone=GMT
		</property>
		<property name="user">root</property>
		<property name="password">12345678</property>
		<!--   连接池参数 -->
		<!-- 初始化连接数 -->
		<property name="initialPoolSize">5</property>
		<!-- 最大连接数 -->
		<property name="maxPoolSize">8</property>
		<!-- 超时时间:当连接池耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 
			0 -->
		<property name="checkoutTimeout">3000</property>
	</named-config>
</c3p0-config>
  1. 创建核心对象 数据库连接池对象 ComboPooledDataSource
  2. 获取连接: getConnection
package c3p0_conn_pool;

import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Test01 {
	// c3p0数据库连接池对象
	static ComboPooledDataSource datasource = null;

	public static void main(String[] args) throws SQLException {
		// 创建连接池对象
		datasource = new ComboPooledDataSource();
		// 基础参数配置
		datasource.setJdbcUrl(
				"jdbc:mysql://127.0.0.1:3306/db6?charset=utf8mb4&useSSL=false&useTimezone=true&serverTimezone=GMT%2B8");
		datasource.setUser("root");
		datasource.setPassword("12345678");

		// 设置连接池的配置参数
		datasource.setInitialPoolSize(3);// 初始化连接对象
//		datasource.setMinPoolSize(2);// 最小连接数量
		datasource.setMaxPoolSize(10);// 最大连接池数量
		datasource.setCheckoutTimeout(3000);// 等待时间(单位:毫秒)

		for (int i = 1; i <= 11; i++) {
			Connection connection = datasource.getConnection();
			System.out.println(connection);
			if (i == 5) {
				connection.close();// 将连接对象归还给连接池,进行复用
			}
		}
	}
}

package c3p0_conn_pool;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Test02 {
	static DataSource dataSource = null;

	public static void main(String[] args) throws SQLException {
		// 1.创建连接池对象
		dataSource = new ComboPooledDataSource();
//		for (int i = 1; i <= 11; i++) {
		// 2.获取连接对象
//			Connection connection = dataSource.getConnection();
//			System.out.println(connection);
//			if (i == 5) {
//				connection.close();// 将连接对象归还给连接池,进行复用
//			}
//		}

		// 2.获取连接对象
		Connection conn = dataSource.getConnection();
		System.out.println(conn);

		PreparedStatement pre = conn.prepareStatement("select * from emp");
		ResultSet resultSet = pre.executeQuery();
		while (resultSet.next()) {
			System.out.println(resultSet.getInt(1));
		}
	}
}

package c3p0_conn_pool;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Test03 {
	static DataSource dataSource = null;

	public static void main(String[] args) throws SQLException {
		// 1.创建连接池对象
		dataSource = new ComboPooledDataSource("otherc3p0");
		// 2.获取连接对象
		Connection conn = dataSource.getConnection();
		System.out.println(conn);

		PreparedStatement pre = conn.prepareStatement("select * from emp");
		ResultSet resultSet = pre.executeQuery();
		while (resultSet.next()) {
			System.out.println(resultSet.getInt(1));
		}
	}
}

Druid:数据库连接池实现技术,由阿里巴巴提供的

  1. 导入jar包 druid-1.0.9.jar

  1. 定义配置文件

是properties形式的

可以叫任意名称,可以放在任意目录下

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db6?serverTimezone=GMT
username=root
password=12345678
initialSize=5
maxActive=10
maxWait=3000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
  1. 加载配置文件。Properties
  2. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
  3. 获取连接:getConnection
package druid_conn_pool;

import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

public class Test01 {
	public static void main(String[] args) throws Exception {
		//1.导入jar包
		//2.定义配置文件
		//3.加载配置文件
		Properties properties = new Properties();
		properties.load(Test01.class.getResourceAsStream("/druid.properties"));
		//4.获取连接池对象
		DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
		//5.获取数据库连接Connection
		Connection connection = dataSource.getConnection();
		System.out.println(connection);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907881.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM+微信小程序的订餐管理系统(点餐2)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的订餐管理系统实现了管理员和用户。管理端实现了 首页、个人中心、用户管理、菜品分类管理、菜品信息管理、订单信息管理、配送信息管理、菜品评价管理、订单投诉管理、…

MRCTF2020:你传你ma呢

文件上传题先判断黑白名单过滤&#xff0c;先传个最简单的木马 这里上传不了php文件&#xff0c;猜测可能是对php文件进行了过滤&#xff0c;将文件改为任意后缀这里改为.abc 还是上传不成功&#xff0c;猜测可能对MIME也做了过滤&#xff0c;将Content-Type更改为image/jpeg再…

设计模式09-行为型模式2(状态模式/策略模式/Java)

5.4 状态模式 5.4.1 状态模式的定义 1.模式动机&#xff1a;有些对象具有多种状态&#xff0c;这些状态在某些情况下能够相互转换&#xff0c;对象在不同的状态下将具有不同的行为&#xff0c;将拥有状态的对象中和状态的行为分离。 2.模式定义&#xff1a;允许一个对象在其…

tauri中shell的特殊字符

tauri中shell的特殊字符 官网例子&#xff1a;https://tauri.app/plugin/shell/ 中的入参是 \S 入参&#xff0c;但如果入参存在空格等特殊字符串&#xff0c;将无法传入 "permissions": [{"identifier": "shell:allow-execute","allow&qu…

电子电气架构 --- Trace 32(劳特巴赫)多核系统的调试

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

使用Web Workers实现JavaScript的多线程编程

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Web Workers实现JavaScript的多线程编程 引言 Web Workers 简介 创建和使用 Worker 通信机制 主线程向 Worker 发送消息 Wor…

【uni-app】创建自定义模板

1. 步骤 打开自定义模板文件夹 在此文件夹下创建模板文件&#xff08;注意后缀名&#xff09; 重新点击“新建页面” 即可看到新建的模板 2. 注意事项 创建的模板必须文件类型对应&#xff08;vue模板就创建*.vue文件, uvue模板就创建*.uvue文件&#xff09;

【云原生】Docker搭建开源翻译组件Deepl使用详解

目录 一、前言 二、微服务项目使用翻译组件的场景 2.1 多语言用户界面 2.2 业务逻辑中的翻译需求 2.3 满足实时通信的要求 2.4 内容管理系统 2.5 个性化推荐系统 2.6 日志和监控 三、开源类翻译组件解决方案 3.1 国内翻译组件方案汇总 3.1.1 百度翻译 3.1.2 腾讯翻…

Hms?: 1渗透测试

靶机&#xff1a;Hms?: 1 Hms?: 1 ~ VulnHub 攻击机&#xff1a;kail linux 2024 主机扫描阶段发现不了靶机&#xff0c;所以需要按DriftingBlues2一样手动配置网卡 1,将两台虚拟机网络连接都改为NAT模式&#xff0c;并查看靶机的MAC地址 2&#xff0c;攻击机上做主机扫描发现…

linux-环境变量

环境变量是系统提供的一组 name value 的变量&#xff0c;不同的变量有不同的用途&#xff0c;通常都具有全局属性 env 查看环境变量 PATH PATH是一个保存着系统指令路径的一个环境变量&#xff0c;系统提供的指令不需要路径&#xff0c;直接就可以使用就是因为指令的路径…

基于Spring Boot的私房菜定制上门服务系统的设计与实现

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统私房菜定制上门服务系统信息管理难度大&#xff0c;容错率…

qt QMenuBar详解

1、概述 QMenuBar是Qt框架中用于创建菜单栏的类&#xff0c;它继承自QWidget。QMenuBar通常位于QMainWindow对象的标题栏下方&#xff0c;用于组织和管理多个QMenu&#xff08;菜单&#xff09;和QAction&#xff08;动作&#xff09;。菜单栏提供了一个水平排列的容器&#x…

转载:【lwip】03-内存管理 - 李柱明 - 博客园

目录 前言3. 内存管理 3.1 内存分配策略 3.1.1 固定大小的内存块3.1.2 可变大小分配3.2 动态内存池&#xff08;pool&#xff09; 3.2.1 介绍3.2.2 内存池的预处理3.2.3 内存池的初始化3.2.4 内存分配3.2.5 内存释放3.2.6 内存池源码定义简要分析 定义内存池资源源码分析保存各…

「Mac畅玩鸿蒙与硬件25」UI互动应用篇2 - 计时器应用实现

本篇将带领你实现一个实用的计时器应用&#xff0c;用户可以启动、暂停或重置计时器。该项目将涉及时间控制、状态管理以及按钮交互&#xff0c;是掌握鸿蒙应用开发的重要步骤。 关键词 UI互动应用时间控制状态管理用户交互 一、功能说明 在这个计时器应用中&#xff0c;用户…

使用MongoDB Atlas构建无服务器数据库

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用MongoDB Atlas构建无服务器数据库 MongoDB Atlas 简介 注册账户 创建集群 配置网络 设置数据库用户 连接数据库 设计文档模式…

从零开始的c++之旅——继承

1. 继承 1.继承概念及定义 继承是面向对象编程的三大特点之一&#xff0c;它使得我们可以在原有类特性的基础之上&#xff0c;增加方法 和属性&#xff0c;这样产生的新的类&#xff0c;称为派生类。 继承 呈现了⾯向对象程序设计的层次结构&#xff0c;以前我们接触的…

正向解析和反向解析

正向解析 服务端&#xff1a; [rootlocalhost rhel]# vim /etc/named.conf [rootlocalhost named]# vim /var/named/named.openlab.com 客户端&#xff1a; [rootlocalhost rhel]# nslookup 反向解析 服务端&#xff1a; [rootlocalhost rhel]# vim /etc/named.conf [ro…

计算机网络:网络层 —— 路由信息协议 RIP

文章目录 路由选择协议动态路由协议路由信息协议 RIPRIP 的重要特点RIP的基本工作过程RIP的距离向量算法RIP存在的问题RIP版本和相关报文的封装 路由选择协议 因特网是全球最大的互联网&#xff0c;它所采取的路由选择协议具有以下三个主要特点&#xff1a; 自适应&#xff1a…

基于yolov5的输电线,电缆检测系统,支持图像检测,视频检测和实时摄像检测功能(pytorch框架,python源码)

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; yolov5&#xff0c;输电线(线缆)检测系统&#xff0c;系统既支持图像检测&#xff0c;也支持视频和摄像实时检测【pytorch框架】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的输…

删除WPS的智能识别目录

很烦&#xff0c;对吧 智能识别目录很垃圾&#xff0c;无法直接删除&#xff0c;如果你选择左边的目录&#xff0c;删除的话&#xff0c;会顺便把右边的正文也删除了。 那么如何只删除左边目录&#xff0c;保留右边的正文呢&#xff1f;只有一个办法&#xff1a; ctrlshiftC复…