java中连接Mysql以及PreparedStatement如何防止sql注入

目录

JDBC

使用JDBC连接到MySQL

使用 Statement

使用 PreparedStatement

Statement 和 PreparedStatement 区别


在 java 中如何连接到 MySQL 数据库,执行 SQL 查询,并处理查询结果?

JDBC

java 程序连接到 mysql,首先需要下载 JDBC 驱动程序。JDBC是一个允许 Java 程序连接到数据库并与之交互的库。

JDBC 驱动程序通常是一个 JAR 文件:MySQL :: Download Connector/J

下载后将该 jar 文件放在项目任意文件夹中,在 idea 中选中该 JAR 文件右键,选择添加到库即可。这样,当Java程序尝试加载JDBC驱动程序时,JVM(Java虚拟机)能够在类路径中找到并加载它。

使用JDBC连接到MySQL

在使用 Java 的 JDBC 连接到 MySQL 数据库时,有两种主要的方法来执行 SQL 语句:Statement 和 PreparedStatement。这两种方法各有优缺点,适用于不同的场景。

使用 Statement

在 Java 的数据库编程中,Statement 对象是一个非常重要的接口。

  • 定义Statement 是用于执行静态 SQL 语句并返回它所生成结果的接口。
  • 特点
    • 每次执行 SQL 语句时,数据库都需要重新解析和编译 SQL 语句,这会影响性能。
    • 容易受到 SQL 注入攻击,因为 SQL 语句和参数是动态拼接的。
    • 适用于执行一次性的、不带参数的 SQL 语句。

如下以拼接的方式执行sql语句,易受到sql注入的攻击

package demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class MySQLConnectionExample {// 数据库连接信息private static final String DB_URL = "jdbc:mysql://localhost:3306/security";private static final String USER = "root";private static final String PASS = "root";public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// 打开连接System.out.println("Connecting to database...");connection = DriverManager.getConnection(DB_URL, USER, PASS); //连接到数据库,如果连接成功,connection 变量将引用一个有效的数据库连接。// 如果连接成功,打印一条消息if (connection != null) {System.out.println("Successfully connected to the database!");// 通过调用 connection.createStatement() 方法创建一个 Statement 对象,用于执行 SQL 查询。statement = connection.createStatement();//以拼接的方式执行sql语句,易受到sql注入的攻击String n = "2";// 执行 SQL 查询String sql = "SELECT * FROM security.users WHERE id=" + n + " LIMIT 0,1";resultSet = statement.executeQuery(sql);// 处理查询结果while (resultSet.next()) {System.out.println("sql查询成功:" + sql);String id = resultSet.getString("id");String username = resultSet.getString("username");String password = resultSet.getString("password");// 打印结果或进行其他处理System.out.println("id: " + id);System.out.println("Username: " + username);System.out.println("password: " + password);// 可以根据需要添加更多列的处理}}} catch (SQLException e) {// 处理 JDBC 错误e.printStackTrace();} finally {// 关闭 ResultSettry {if (resultSet != null) {resultSet.close();}} catch (SQLException ex) {ex.printStackTrace();}// 关闭 Statementtry {if (statement != null) {statement.close();}} catch (SQLException ex) {ex.printStackTrace();}// 关闭 Connectiontry {if (connection != null) {connection.close();}} catch (SQLException ex) {ex.printStackTrace();}}}
}

使用 PreparedStatement

  • 定义PreparedStatementStatement 的子接口,用于执行带参数的预编译 SQL 语句。
  • 特点
    • 预编译 SQL 语句,提高性能。编译后的 SQL 语句可以多次执行而不需要重新解析。
    • 防止 SQL 注入攻击,因为参数是通过占位符(通常是问号 ?)进行绑定的,数据和查询逻辑是分开的。
    • 适用于需要多次执行相同 SQL 语句但使用不同参数的情况。

执行后 sql 语句显示如下,貌似能被注入

SELECT * FROM security.users WHERE id='1' and 1=2 --+' LIMIT 1

但其实 PreparedStatement 会将参数值作为单独的参数传递给数据库,而不是直接拼接到 SQL 语句中。所以 1' and 1=2 --+ 只是作为一个参数值赋值给 id。实际执行的是如下 sql 语句

SELECT * FROM security.users WHERE id='1\' and 1=2 --+' LIMIT 1

而这条语句实际执行效果等于如下语句。因为 mysql 会尝试将 1\' and 1=2 --+ 转换为整数 1,具体可以看MySQL 的隐式类型转换,从而防止了 sql 注入。

SELECT * FROM security.users WHERE id='1' LIMIT 1

package demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class MySQLConnectionExample {// 数据库连接信息private static final String DB_URL = "jdbc:mysql://localhost:3306/security";private static final String USER = "root";private static final String PASS = "root";public static void main(String[] args) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {// 打开连接System.out.println("Connecting to database...");connection = DriverManager.getConnection(DB_URL, USER, PASS);// 如果连接成功,打印一条消息if (connection != null) {System.out.println("Successfully connected to the database!");// 准备 SQL 语句,使用占位符 ?String sql = "SELECT * FROM security.users WHERE id=? LIMIT 1";preparedStatement = connection.prepareStatement(sql);// 设置占位符的值, 其中 1 是占位符的位置(从 1 开始计数),userId 是要设置的值。String userId = "1' and 1=2 --+"; // 假设要查询的用户 ID 为 1preparedStatement.setString(1, userId);// 执行 SQL 查询resultSet = preparedStatement.executeQuery();// 处理查询结果while (resultSet.next()) {System.out.println("SQL 查询成功");String id = resultSet.getString("id");String username = resultSet.getString("username");String password = resultSet.getString("password");// 打印结果或进行其他处理System.out.println("id: " + id);System.out.println("Username: " + username);System.out.println("password: " + password);// 可以根据需要添加更多列的处理}}} catch (SQLException e) {// 处理 JDBC 错误e.printStackTrace();} finally{// 关闭 ResultSettry {if (resultSet != null) {resultSet.close();}} catch (SQLException ex) {ex.printStackTrace();}// 关闭 PreparedStatementtry {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException ex) {ex.printStackTrace();}// 关闭 Connectiontry {if (connection != null) {connection.close();}} catch (SQLException ex) {ex.printStackTrace();}}}
}

Statement 和 PreparedStatement 区别

  • 性能PreparedStatement 通常比 Statement 性能更高,因为它允许数据库预编译 SQL 语句。
  • 安全性PreparedStatement 能够防止 SQL 注入攻击,而 Statement 则容易受到这种攻击。
  • 适用场景Statement 适用于执行一次性的、不带参数的 SQL 语句;而 PreparedStatement 则适用于需要多次执行相同 SQL 语句但使用不同参数的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年看项目管理软件与工程项目管理的奇妙融合

一、禅道在项目管理中的全面应用 禅道在产品管理方面,能够清晰地对产品的需求进行全方位管理。从需求的提出到详细信息的记录,再到状态、负责人以及完成进度的跟踪,都能有条不紊地进行。产品经理可以通过禅道制定合理的产品规划,…

实用宝典:元器件外贸独立站电子元件数据库设置完全手册

对于投身于元器件外贸领域的企业来说,如何建立一个既能凸显自身特色又具备高度功能性与良好用户体验的独立站?而在这一过程中,#电子元件数据库#作为独立站的核心要素之一,它的构建质量和管理方式又将如何直接影响网站的整体竞争力…

BMS、EMS PCS 简介

1 储能系统的构成 完整的电化学储能系统主要由电池组、电池管理系统(BMS)、能量管理系统(EMS)、储能变流器(PCS)以及其他电气设备构成。 在储能系统中,电池组将状态信息反馈给电池管理系统BMS&…

zookeeper客户端

启动单机版的zookeeper 配置Maven环境 (1) IDEA自带maven (2) 更新Maven库镜像地址: ① 拷贝D:\Program Files\JetBrains\IntelliJ IDEA 2018.3.5\plugins\maven\lib\maven3\conf\settings.xml [IntelliJ的安装目录]到 C:/用户/username/.m2 (如果.m2文件不存在&…

前后分离项目记录

一.前端设置 1.打包问题 打包报错 Thread Loader时,增加以下代码: 2.上线时api设置 二.Nginx问题 1.缓存问题:添加如下代码以禁止缓存,否则在关闭nginx后仍然可以访问页面 2.跨域问题在后端加CrossOrigin注解即可 3.上线时co…

人工智能风险预警以及区块链解决方案探索

​​发表时间:2024年9月26日 一个专家小组在为世界经济论坛撰写的报告中警示道,人工智能(以下均简称为AI)技术增加了各类组织遭受攻击的风险,并带来了训练数据污染和提示词注入攻击等新威胁。由于训练和测试数据库的庞…

3 机器学习之假设空间

归纳(induction)与演绎(deduction)是科学推理的两大基本手段。前者是从特殊到一般的“泛化”(generalization)过程,即从具体的事实归结出一般性规律;后者则是从一般到特殊的“特化”(specialization)过程,即从基础原理推演出具体状况。例如&a…

笔试强训10.14

注意&#xff1a; 1.使用strcpy是把右参数赋值给左参数&#xff0c;而且左参数必须有终止符\0。 2.注意当输入的字符串的最长连续数字串在最后时&#xff0c;此时就不会进行else的判断&#xff0c;需要出了while循环后再进行判断。 #include <iostream> #include <…

Java面试宝典-WEB学习

Java web学习 目录 Java web学习 1、说说 Servlet 的基本架构 2、说一说 Servlet 的生命周期? 3、如何实现一个自定义的 servlet&#xff1f; 4、servlet中有哪些核心类&#xff1f;都有什么特点&#xff1f; 5、什么情况下调用 doGet()和 doPost()&#xff1f; 6、request.ge…

Attention Is All You Need论文翻译

论文名称 注意力即是全部 论文地址 https://user.phil.hhu.de/~cwurm/wp-content/uploads/2020/01/7181-attention-is-all-you-need.pdf 摘要 主流的序列转导模型基于复杂的递归或卷积神经网络&#xff0c;这些网络包含编码器和解码器。性能最好的模型通过注意力机制将编码器和…

谷歌-BERT-第一步:模型下载

1 需求 需求1&#xff1a;基于transformers库实现自动从Hugging Face下载模型 需求2&#xff1a;基于huggingface-hub库实现自动从Hugging Face下载模型 需求3&#xff1a;手动从Hugging Face下载模型 2 接口 3.1 需求1 示例一&#xff1a;下载到默认目录 from transform…

第十一章 RabbitMQ之消费者确认机制

目录 一、介绍 二、演示三种ACK方式效果 2.1. none: 不处理 2.1.1. 消费者配置代码 2.1.2. 生产者主要代码 2.1.3. 消费者主要代码 2.1.4. 运行效果 2.2. manual&#xff1a;手动模式 2.3. auto&#xff1a;自动模式 一、介绍 消费者确认机制&#xff08;Consume…

架构设计笔记-13-层次式架构设计理论与实践

目录 知识要点 综合知识 案例分析 1.SSM框架 2.MVC模式&#xff0c;XML 3.MVC架构脆弱性 4.容器技术的优势 5.对象关系映射ORM技术 知识要点 一般来说&#xff0c;架构可以分为表现层、中间层和持久层三个层次。 表现层&#xff1a;表现层主要负责接收用户的请求&…

k8s ETCD数据备份与恢复

在 Kubernetes 集群中&#xff0c;etcd 是一个分布式键值存储&#xff0c;它保存着整个集群的状态&#xff0c;包括节点、Pod、ConfigMap、Secrets 等关键信息。因此&#xff0c;定期对 etcd 进行备份是非常重要的&#xff0c;特别是在集群发生故障或需要恢复数据的情况下。本文…

网站建设为什么要选择国内服务器

选择国内服务器进行网站建设&#xff0c;对于面向国内用户的企业来说&#xff0c;是一个明智的决策。以下是一些选择国内服务器的主要原因&#xff1a; 提升用户体验&#xff1a; 网站访问速度是用户体验的关键因素之一。由于物理距离较近&#xff0c;国内服务器通常能提供更快…

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(1)

移情别恋c ദ്ദി˶&#xff70;̀֊&#xff70;́ ) ——14.哈希(1) unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 l o g 2 N log_2 N log2​N&#xff0c;即最差情况下需要比较红黑树的高度次…

prompt learning

prompt learning 对于CLIP&#xff08;如上图所示&#xff09;而言&#xff0c;对其prompt构造的更改就是在zero shot应用到下游任务的时候对其输入的label text进行一定的更改&#xff0c;比如将“A photo of a{obj}”改为“[V1][V2]…[Vn][Class]”这样可学习的V1-Vn的token…

利用配置错误的负载均衡器,通过XSS窃取Cookies

引言 在本文中&#xff0c;我们将探讨一个涉及负载均衡器漏洞利用和跨站脚本攻击&#xff08;XSS&#xff09;来劫取应用程序Cookies的实际场景。由于保密协议的限制&#xff0c;我们将省略具体名称和截图&#xff0c;但我们会详细分析攻击过程及其影响。通过将负载均衡器的主…

MySQL中 truncate、drop和delete的区别

MySQL中 truncate、drop和delete区别 truncate 执行速度快&#xff0c;删除所有数据&#xff0c;但是保留表结构不记录日志事务不安全&#xff0c;不能回滚可重置自增主键计数器 drop 执行速度较快&#xff0c;删除整张表数据和结构不记录日志事务不安全&#xff0c;不能回…

LabVIEW示波器通信及应用

基于LabVIEW平台开发的罗德与施瓦茨示波器通信与应用系统实现了示波器的远程控制及波形数据的实时分析&#xff0c;通过TCP/IP或USB接口与计算机通信&#xff0c;利用VISA技术进行指令传输&#xff0c;从而实现高效的数据采集与处理功能。 项目背景 随着现代电子测试需求的日益…