【Java SE】PreparedStatement

PreparedStatement 是一个接口,它继承自 Statement,用于预编译 SQL 语句。简单来说,PreparedStatement 是 JDBC 提供的一个对象,用于执行 SQL 语句。它的重要功能是帮助防止 SQL 注入攻击,并提高执行效率。

SQL 注入问题

以用户登录为例,通常用户需要先注册一个用户名,并且为这个用户名设置一个对应的密码,通过正确的用户名和匹配的密码才能登录系统。如果用户名不存在或者密码有误,则无法登录系统。然而,SQL 注入则能“无视”这个密码检查的过程,通过一段特定的密码文本,就能在用户名不存在或密码错误的情况下仍然顺利登录系统。

例如,在一个安全新不够高的系统中,通过 ' or '1' = '1这样一段文本就能成功地登录该系统,即便用户名不存在或这段文本并非匹配的密码。这就是 SQL 注入的一个实例。这个简单实例背后的原理是:在后端进行账户信息检查时,会利用前端传来的用户名和密码到数据库中查询是否存在满足条件的行,过程与下面的代码类似:

String sql = "SELECT * FROM users WHERE username = '" + name + "' and password = '" + pwd + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);if (rs.next()) {// 执行登录成功后的逻辑System.out.println("登录成功");
} else {// 执行登录失败后的逻辑System.out.println("登录失败");
}

在这个过程中,我们使用了 JDBC 中常用的 Statement 对象执行 SQL 语句。乍一看,后端拼接的 SQL 语句没有什么问题,但是,用前文提及的 ' or '1' = '1替换密码 pwd 后,就会发现问题。假设这里输入的用户名为 a,拼接后的 SQL 语句为:

SELECT * FROM users WHERE username = 'a' and password = '' or '1' = '1'

对 SQL 语句进行分析可以知道,username = 'a' and password = ''先执行,不管这句的结果如何,or 后面的部分恒成立,即无论输入的用户名和密码是什么,都能执行成功并且返回所有数据。因此,用户可以通过 SQL 注入随意登录系统。为了防止 SQL 注入的发生,Java 推出了 PreparedStatement。

SQL 注入防范

我们使用 PreparedStatement 预防 SQL 注入,具体过程为:

(1)获取 PreparedStatement 对象

// 使用 `?` 占位符替代 SQL 语句中的参数值
String sql = "SELECT * FROM users WHERE username = ? and password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);

(2)设置参数值

// 设置参数值,根据索引赋值,索引从 1 开始计数
pstmt.setString(1, name);
pstmt.setString(2, pwd);

(3)执行 SQL 语句

// 执行 SQL 语句,不需要再传入 sql
ResultSet rs = pstmt.executeQuery();

这个过程中,解决 SQL 注入的原理是:将传入参数中包含的敏感字符进行转移,比如对单引号进行转义,将参数中的' 转义成 \',以此避免与 SQL 语句中的 ' 混淆。

预编译原理

使用 PreparedStatement 除了能通过将敏感字符进行转移来防止 SQL 注入外,还可以预编译 SQL,提高性能。

在这里插入图片描述

通常,Java 代码将 SQL 语句发送给 MySQL 服务器后,服务器会检查 SQL 语法,再编译 SQL,最后执行 SQL,如上图所示。前两者花费的时间比后者大。

在使用 Statement 执行拼接得到的 SQL 语句时,每次都需要获取一个拼接好的 SQL 语句,并发送给 MySQL 服务器,这时服务器都需要执行上述的三个步骤,效率较低。而预编译语句则不同,使用占位符生成 SQL 模板,并且将模板先发送给 MySQL 服务器,这时服务器会直接执行检查 SQL 语法和编译 SQL。在 SQL 模板不变的情况下,当有新的参数传递过来时,只需要用参数替换占位符并且跳过前两个步骤直接执行 SQL 即可,效率有所提升。需要注意的是,预编译功能需要通过将 url 中的参数 useServerPrepStmts 设置为 true 来开启:

String url = "jdbc:mysql://127.0.0.1:3306/db?useSSL=false&useServerPrepStmts=true";

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

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

相关文章

集群聊天服务器(7)数据模块

目录 Mysql数据库代码封装头文件与源文件 Mysql数据库代码封装 业务层代码不要直接写数据库,因为业务层和数据层的代码逻辑也想完全区分开。万一不想存储mysql,想存redis的话,就要改动大量业务代码。解耦合就是改起来很方便。 首先需要安装m…

数造科技亮相第26届高交会并接受媒体采访,以数据智能赋能未来

11 月 14 日至 16 日,第二十六届中国国际高新技术成果交易会(简称“高交会”)在深圳成功举办。本届大会以“科技引领发展,产业融合聚变”为主题,汇聚了全球最新的科技成果,打造了一场科技界的盛大聚会。 在…

C#获取视频第一帧_腾讯云媒体处理获取视频第一帧

一、 使用步骤: 第一步、腾讯云开启万象 第二步、安装Tencent.QCloud.Cos.Sdk 包 第三步、修改 腾讯云配置 图片存储目录配置 第四步、执行获取图片并保存 二、封装代码 using System.Text; using System.Threading.Tasks;using COSXML.Model.CI; using COSXML.A…

概念解读|K8s/容器云/裸金属/云原生...这些都有什么区别?

随着容器技术的日渐成熟,不少企业用户都对应用系统开展了容器化改造。而在容器基础架构层面,很多运维人员都更熟悉虚拟化环境,对“容器圈”的各种概念容易混淆:容器就是 Kubernetes 吗?容器云又是什么?容器…

吴恩达深度学习笔记:序列模型(Sequence Models) 1.3-1.4

目录 第五门课 序列模型(Sequence Models)第一周 循环序列模型(Recurrent Neural Networks)1.3 循环神经网络模型(Recurrent Neural Network Model)1.4 通过时间的反向传播(Backpropagation through time) …

语义分割(semantic segmentation)

语义分割(semantic segmentation) 文章目录 语义分割(semantic segmentation)图像分割和实例分割代码实现 语义分割指将图片中的每个像素分类到对应的类别,语义区域的标注和预测是 像素级的,语义分割标注的像素级的边界框显然更加精细。应用&#xff1a…

C++ —— string类(上)

目录 string的介绍 string类功能的使用介绍 constructor —— 构造 介绍使用(1)(2)(4) :构造、拷贝构造、带参构造 介绍(3):拷贝string类对象的一部分字符…

Python小白学习教程从入门到入坑------第三十二课 生成器(语法进阶)

目录 一、生成器 generator 1.1 生成器表达式 1.1.1 表达式一 1.1.2 表达式二 二、可迭代对象、迭代器、生成器三者之间的关系 2.1 定义与特性 2.2 关系与区别 一、生成器 generator 在Python中,生成器(Generators)是一种用于迭代对象…

商业iOS端路由架构演进

背景 目前商业SDK中的点击事件,会根据不同的「事件类型」「业务类型」,去执行不同的路由跳转逻辑,然而不同的跳转事件内部又有着很复杂的跳转逻辑, 痛点 不同的跳转逻辑之间存在耦合 例如,在deeplink的跳转逻辑之中…

数据结构(单向链表——c语言实现)

链式存储的优缺点: 优点: 1、动态分配内存: 链式存储不需要在数据插入之前分配固定大小的数组或内存块,因此它更适合存储动态变化的数据 2、高效的插入和删除操作: 在链表中插入或删除元素只需要调整相邻节点的指…

【SQL】E-R模型(实体-联系模型)

目录 一、介绍 1、实体集 定义和性质 属性 E-R图表示 2. 联系集 定义和性质 属性 E-R图表示 一、介绍 实体-联系数据模型(E-R数据模型)被开发来方便数据库的设计,它是通过允许定义代表数据库全局逻辑结构的企业模式&#xf…

Pytest-Bdd-Playwright 系列教程(12):步骤参数 parsers参数解析

Pytest-Bdd-Playwright 系列教程(12):步骤参数 & parsers参数解析 前言一、什么是步骤参数?二、pytest-bdd 的步骤参数用法2.1 简单字符串解析2.2 自定义正则表达式解析2.3 参数类型转换 三、案例:基于 pytest-bdd…

vscode 快捷键生成代码

1. !Tab/回车键 便捷生成html初始结构代码(注意!是英文字符) 2. Alt B 快捷默认浏览器打开 3. Ctrl / 增加注释 4. 光标放到该行即可,直接ctrlC,ctrlv,即可在下面复制一行 5. 选中要修改的标签…

前端接入Paymax支付请求

材料指南 开发者平台 :配置开发必备信息(appid,商户号,公钥私钥),此处与请求参数appId、merchantNo有关。 PayerMax Apis:各支付接口信息,本文以收银台支付API为请求展开,请求url为orderAndPay,测试环境基…

Jmeter的后置处理器(二)

5--JSR223 PostProcessor 功能特点 自定义后处理逻辑:使用脚本语言编写自定义的后处理逻辑。支持多种脚本语言:支持 Groovy、JavaScript、BeanShell 等脚本语言。动态参数传递:将提取的数据存储为变量,供后续请求使用。灵活性高…

CSS遮罩:mask

CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 ✍🏻作者简介:致…

15. Python中的os.path模块/路径操作相关

这个专栏记录我学习/科研过程中遇到的一些小问题以及解决方案,一些问题可能比较蠢请见谅。自用,仅供参考。 ------------------------------------------------------------------------------------ Python中的os.path模块详解(包括一些常…

鸿蒙实战:页面跳转传参

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙项目2.2 编写首页代码2.3 新建第二个页面 3. 测试效果4. 实战总结 1. 实战概述 本次实战,学习如何在HarmonyOS应用中实现页面间参数传递。首先创建项目,编写首页代码,实现按钮跳转至第二个页面并…

NLP论文速读(EMNLP 2024)|动态奖励与提示优化来帮助语言模型的进行自我对齐

论文速读|Dynamic Rewarding with Prompt Optimization Enables Tuning-free Self-Alignment of Language Models 论文信息: 简介: 本文讨论的背景是大型语言模型(LLMs)的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…