news 2026/4/15 17:32:33

JDBC和SQL注入学习笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JDBC和SQL注入学习笔记

JDBC

JDBC全称Java Database Connectivity,即Java数据库连接器,是Java提供的专门执行SQL的API,包含在java.sql和javax.sql包里。

Java程序要连接数据库执行SQL,还需要安装数据库管理软件驱动,比如要连接MySQL,需要导入mysql-connector的jar包。

可以把JDBC的作用,可以与Navivcat等数据库可视化操作工具类比,比如:连接数据库、执行SQL、管理事务等。

JDBC的使用步骤比较固定:

  1. 加载驱动程序:使用Class.forName()加载数据库驱动(JDBC 4.0以后可以自动加载,无需显性编写这个步骤的代码)。
  2. 建立连接:使用DriverManager.getConnection()获取数据库连接,获得Connection对象,代表与数据库的连接对象。
  3. 创建语句:使用Connection对象创建StatementPreparedStatementCallableStatement。这些Statement对象代表一个SQL。
  4. 执行SQL:执行SQL并获取ResultSet。ResultSet对象代表查询结果集。
  5. 处理结果:可以遍历ResultSet获取数据。
  6. 关闭资源:按顺序关闭ResultSetStatementConnection

示例代码:

importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.Statement;// 使用JDBC API进行数据库连接并执行SQL语句 public class JdbcDemo1 {publicstatic void main(String[]args){// 定义数据库连接信息:// URL固定格式jdbc:mysql://主机名(ip或域名):端口号/数据库名称?useSSL=true&characterEncoding=utf8&useUnicode=true(参数K:参数V...)String url="jdbc:mysql://localhost:3306/practice_join?useSSL=true&characterEncoding=utf8&useUnicode=true";// 用户名和密码Stringuser="user";String password="password";// 执行SQL语句(注意:需要在Navicat等可视化工具中运行过,确保SQL语法正确)Stringsql="SELECT s.`student_id` AS student_id, s.`student_name` AS student_name, c.`class_name` AS class_name\n"+"FROM `student` AS s\n"+"LEFT JOIN `class` AS c\n"+"ON s.`class_id`=c.`class_id`";// 使用try-catch-resources语句处理异常,便于释放资源try(Connection conn=DriverManager.getConnection(url,user,password);Statement stmt=conn.createStatement();// 创建SQL语句对象ResultSet rs=stmt.executeQuery(sql);// 执行SQL,返回结果集){ System.out.println("数据库连接成功");// 处理结果集,打印出每一列的结果到控制台while(rs.next()){intstudent_id=rs.getInt("student_id");// 该类为整数类型,可以使用getInt()方法获取String student_name=rs.getString("student_name");// 该类为字符串类型,可以使用getString()方法获取String class_name=rs.getString("class_name");System.out.println(student_id+" "+student_name+" "+class_name);} } catch(Exception e){ System.out.println("数据库连接失败");e.printStackTrace();} } }

JDBC核心接口和类

  1. DriverManager类。用来管理JDBC驱动程序的基本服务。最常用的是static Connection getConnection(String url, String user, String password)方法,尝试与给定数据库URL建立连接。注意,不同的数据库的URL变量固定格式是不同的,MySQL的格式为:
// MySQL url固定格式jdbc:mysql://主机名(ip或域名):端口号/数据库名称?useSSL=true&characterEncoding=utf8&useUnicode=true(参数K:参数V...)Stringurl="jdbc:mysql://localhost:3306/practice_join?useSSL=true&characterEncoding=utf8&useUnicode=true";
  1. Connection接口。表示与特定数据库的连接(会话)。常用方法有:
  • Statement createStatement():创建一个Statement对象,用于将SQL语句发送到数据库。
  • PreparedStatement prepareStatement(String sql):创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
  • CallableStatement prepareCall(String sql):创建一个CallableStatement对象,用于调用数据库存储过程。
  • void setAutoCommit(boolean autoCommit):设置此连接是否自动提交事务。
  • void commit():提交事务,使上一次提交/回滚之后的所有更改成为持久更改。
  • void rollback():回滚事务,撤销当前事务中所做的所有更改。
  • void close():立即释放此Connection对象的数据库和JDBC资源。常用try-catch-resources语句处理异常,以便异常出现后程序自动释放资源。
  1. Statement接口。表示执行SQL语句的对象。常用方法:
  • ResultSet executeQuery(String sql):执行给定的SQL语句,返回一个ResultSet对象(通常用于SELECT查询语句),是最常用的方法。
  • int executeUpdate(String sql):执行给定的SQL语句,可能是INSERT、UPDATE或DELETE语句,或者不返回任何内容的SQL语句(如DDL语句)。
  • boolean execute(String sql):执行给定的SQL语句,可能返回多个结果(用于执行返回多个结果集或更新计数的语句)。
  • void close():释放此Statement对象的数据库和JDBC资源。
  1. PreparedStatement接口。PreparedStatement与Statement相似,都是表示执行SQL语句的对象。但PreparedStatement表示预编译的SQL语句,可以防止SQL注入问题。常见方法:
  • void setInt(int parameterIndex, int x):将指定参数设置为给定的int值。
  • void setString(int parameterIndex, String x):将指定参数设置为给定的String值。
  • void setDate(int parameterIndex, Date x):将指定参数设置为给定的java.sql.Date值。
  • void setObject(int parameterIndex, Object x):使用给定对象设置指定参数的值。
  • ResultSet executeQuery():执行此PreparedStatement对象中的SQL查询,并返回ResultSet对象。
  • int executeUpdate():执行此PreparedStatement对象中的SQL更新(INSERT、UPDATE、DELETE等)。
  1. ResultSet接口。表示数据库结果集的数据表,通常是执行SELECT查询语句生成。常用方法:
  • boolean next():将光标从当前位置向前移动一行,如果新行有效则返回true,否则返回false。最常用的方法,用于循环解析处理数据。
  • getXXX(int columnIndex)getXXX(String columnLabel):获取当前行中某列的值,其中XXX是数据类型(如Int、String、Date等),不同的列字段类型,使用不同的方法解析。
  • void close():释放此ResultSet对象的数据库和JDBC资源。

SQL注入问题

SQL执行时,一般是用用户输入数据+编写的SQL片段拼接成完整的SQL语句,比如要查询一个用户表中的信息,Java代码会编写成:

...Connectionconn=DriverManager.getConnection(url,user,password);// 创建链接对象Statementstmt=conn.createStatement();// 创建SQL语句对象// 编写SQL语句,是从用户名和密码输入框输入的inputUser和inputPassword,拼接成完整的SQL语句// 比如:SELECT * FROM `user` WHERE `user`='张三' AND `password`='123456'Stringsql="SELECT * FROM `user` WHERE `user`='"+inputUser+"' AND `password`='"+inputPassword+"'";ResultSetrs=stmt.executeQuery(sql);...

正常查询结果是:

iduserpassword
1张三123456

假设,一个黑客可以在用户名和密码框输入:

inputUserinputPassword
’ OR ‘1’='1’ OR ‘1’='1

最终SQL会被拼接为:

SELECT*FROM`user`WHERE`user`=''OR'1'='1'AND`password`=''OR'1'='1'

这个SQL在条件中,OR '1'='1'总为真,所以会查出表中所有的数据,最终执行结果如下:

iduserpassword
1张三123456
2李四456789
3王五789123

这就是SQL注入!

SQL注入是一种代码注入技术,利用应用程序对用户输入处理不当的漏洞,使得攻击者能够在应用程序的数据库查询中注入并执行恶意的SQL代码。

SQL注入的原理,就是利用字符串拼接的方式,将用户输入直接嵌入到SQL语句中。如果用户输入中包含了恶意的SQL片段,会在字符串拼接后,成为SQL执行命令的一部分,从而导致数据库遭受攻击,包括但不限于:数据泄露、数据篡改、数据删除、绕过身份验证等。

SQL注入问题解决方案

JDBC提供PreparedStatement用来解决SQL注入问题。PreparedStatement与Statement相似,都是表示执行SQL语句的对象。但PreparedStatement表示预编译的SQL语句,会先使用利用问号?做占位符编写的SQL进行编译,之后再替换参数。

上述存在SQL注入问题的代码,用PreparedStatement可以改为:

...Connectionconn=DriverManager.getConnection(url,user,password);// 创建链接对象Stringsql="SELECT * FROM `user` WHERE `user`=? AND `password`=?"// 使用字符?代表需要替换的参数PreparedStatementps=conn.prepareStatement(sql);// 创建PreparedStatement对象ps.ps.setString(1,inputUser);// 将第一个?占位的参数替换为inputUser字符串ps.setString(2,inputPassword);// 将第二个?占位的参数替换为inputPassword字符串ResultSetrs=ps.executeQuery();// 执行SQL语句...

为什么使用PreparedStatement能解决SQL注入问题?

因为PreparedStatement采用预编译的机制,预编译完成后,数据库知道SQL语句的基本结构,比如它已经知道要查询user表,条件是两个等值比较,然后等待参数传入。后续程序通过setXXX 方法(如 setString, setInt)为占位符设置参数值,这些参数值不会被解释为SQL语句的一部分,而是作为纯数据传递。因此,即使参数值中包含SQL关键词或特殊字符(比如单引号),数据库也会将其视为普通字符串,会对其进行转义处理,而不会改变原有SQL语句的结构。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 17:32:20

AI语音克隆+数字人合成,HeyGem实现全流程自动化

AI语音克隆数字人合成,HeyGem实现全流程自动化 在短视频内容爆发式增长的今天,一个核心矛盾日益凸显:高质量数字人视频的制作门槛依然很高——既要专业配音,又要精准口型同步,还得兼顾人物形象、背景风格与多平台适配…

作者头像 李华
网站建设 2026/4/13 18:25:32

Clawdbot整合Qwen3-32B实战教程:日志审计、调用追踪与安全审计配置

Clawdbot整合Qwen3-32B实战教程:日志审计、调用追踪与安全审计配置 1. 为什么需要这套组合:从问题出发的真实需求 你有没有遇到过这样的情况:团队在用大模型做内部知识问答或自动化客服时,突然发现——谁在什么时候问了什么问题…

作者头像 李华
网站建设 2026/4/12 17:53:24

GLM-4V-9B效果对比:量化vs非量化在图像描述任务中的语义保真度

GLM-4V-9B效果对比:量化vs非量化在图像描述任务中的语义保真度 1. 为什么图像描述不能只看“像不像” 你有没有试过让一个AI模型描述一张照片,结果它说对了所有物体,却完全忽略了画面里最打动人的细节?比如一张夕阳下老人牵着孙…

作者头像 李华
网站建设 2026/4/12 14:25:23

YOLOE模型推理效率优化技巧,提速不加硬件

YOLOE模型推理效率优化技巧,提速不加硬件 YOLOE不是又一个“更快的YOLO”,而是一次对目标检测范式的重新思考:它不靠堆显存、不靠换卡、不靠重训大模型,就能在同一块GPU上跑出更高帧率、更低延迟、更强泛化能力。你可能已经试过y…

作者头像 李华
网站建设 2026/4/12 16:44:29

【开题答辩全过程】以 基于ssm的医院耗材管理系统设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

作者头像 李华
网站建设 2026/4/13 11:35:47

VibeVoice Pro在客服场景的应用:实时语音应答系统搭建

VibeVoice Pro在客服场景的应用:实时语音应答系统搭建 1. 为什么传统客服语音响应总让人“等得心焦” 你有没有接过银行或电商的自动语音客服?刚按下数字键,电话那头先是一段长达2秒的沉默,接着才响起“您好,我是智能…

作者头像 李华