java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解大家都知道PreparedStatement对象可以防止sql注入,而Statement不能防止sql注入,那么大家知道为什么PreparedStatement对象可以防止sql注入…

大家好,又见面了,我是你们的朋友全栈君。

java中PreparedStatement和Statement详细讲解

大家都知道PreparedStatement对象可以防止sql注入,而Statement不能防止sql注入,那么大家知道为什么PreparedStatement对象可以防止sql注入,接下来看我的案例大家就会明白了!

我用的是mysql数据库,以admin表为例子,如下图:

最后面有具体的java代码和sql代码案例

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

最终执行的sql语句打印出来是SELECT * FROM admin WHERE username = ‘韦小宝’ AND password = ‘222\’ OR \’8\’=\’8′

从以上截图就能看出来,由此可见,prepareStatement对象防止sql注入的方式是把用户非法输入的单引号用\反斜杠做了转义,从而达到了防止sql注入的目的

Statement对象就没那么好心了,它才不会把用户非法输入的单引号用\反斜杠做转义呢!

PreparedStatement可以有效防止sql注入,所以生产环境上一定要使用PreparedStatement,而不能使用Statement

当然啦,你可以仔细研究下PreparedStatement对象是如何防止sql注入的,我自己把最终执行的sql语句打印出来了,看到打印出来的sql语句就明白了,原来是mysql数据库产商,在实现PreparedStatement接口的实现类中的setString(int parameterIndex, String x)函数中做了一些处理,把单引号做了转义(只要用户输入的字符串中有单引号,那mysql数据库产商的setString()这个函数,就会把单引号做转义)

大家有兴趣可以去网上,下载一份mysql数据库的驱动程序的源代码,看看mysql数据库产商的驱动程序的源代码,去源代码中找到setString(int parameterIndex, String x)函数,看看该函数中是怎么写的,我没有下载mysql数据库产商的驱动程序的源代码,而是把mysql数据库的驱动程序jar包解压了,找到了PreparedStatement.class文件,利用反编译工具,反编译了一下,如下:

java中PreparedStatement和Statement详细讲解java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解

java中PreparedStatement和Statement详细讲解 

java中PreparedStatement和Statement详细讲解 

java中PreparedStatement和Statement详细讲解 这下大家应该知道PreparedStatement是如何防止sql注入的了吧

像222′ OR ‘8’=’8这样的sql注入还算温柔了,有些更可恶的用户,他们输入的非法的值是delete from tableName或truncate table tableName 这是十分危险的,更有甚者传入drop table tableName;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句执行,所以生产环境上一定要使用PreparedStatement,而不能使用Statement

下面再举几个例子,看截图

java中PreparedStatement和Statement详细讲解

最终打印SELECT * FROM admin WHERE username = ‘韦小宝’ AND password = ‘\’; DROP TABLE tableName;#’

java中PreparedStatement和Statement详细讲解

最终打印SELECT * FROM admin WHERE username = ‘韦小宝’ AND password = ‘\’; delete from tableName;#’

java中PreparedStatement和Statement详细讲解

最终打印SELECT * FROM admin WHERE username = ‘韦小宝’ AND password = ‘\’; truncate table tableName;#’

java中PreparedStatement和Statement详细讲解

下面是java代码和sql语句,供大家参考,主要是为了测试PreparedStatement对象,所以java代码写的比较粗略,大家凑合着看吧!

package com.test;

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

/*
 * 研究PreparedStatement是如何防止sql注入的,我分析了一下,原来是mysql数据库产商,在实
 * 现PreparedStatement接口的实现类中的setString(int parameterIndex, String x)函
 * 数中做了一些处理,把单引号做了转义(只要用户输入的字符串中有单引号,那mysql数据库产商的setString()这个函
 * 数,就会把单引号做转义)
 */
public class TestConnMySql2 {

	public static void main(String[] args) {
		String connStr = "jdbc:mysql://localhost:3306/girls";
//		String sql = "select * from admin";
		String sql = "SELECT * FROM admin WHERE username = ? AND password = ?";
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection connection = DriverManager.getConnection(connStr, "root", "root");
			System.out.println("数据库连接=" + connection);
			//Statement无法防止sql注入
//			Statement stmt = connection.createStatement();
	//PreparedStatement可以有效防止sql注入,所以生产环境上一定要使用PreparedStatement,而不能使用Statement
			PreparedStatement prepareStatement = connection.prepareStatement(sql);
			prepareStatement.setString(1, "韦小宝");
			//模拟用户输入正常的值
//			prepareStatement.setString(2, "222");
			//测试sql注入(模拟用户输入非法的值)
			prepareStatement.setString(2, "222' OR '8'='8");
			/*
			 *上面那种的sql注入还算温柔了,有些更可恶的用户,他们输入的非
			 *法的值是delete from tableName或truncate table tableName 这是十分危险的,
			 * 更有甚者传入drop table tableName;有些数据库是不会让你成功的,但也有很多数
			 * 据库就可以使这些语句执行,所以生产环境上一定要使用PreparedStatement,而不能使用Statement
			 */
			//测试sql注入(模拟用户输入非法的值)在mysql中#井号表示单行注释(这是mysql中的基础知识,我就不赘述了)
//			prepareStatement.setString(2, "'; DROP TABLE tableName;#");
			//测试sql注入(模拟用户输入非法的值)
//			prepareStatement.setString(2, "'; delete from tableName;#");
			//测试sql注入(模拟用户输入非法的值)
//			prepareStatement.setString(2, "'; truncate table tableName;#");
			
			ResultSet rs = prepareStatement.executeQuery();
			System.out.println("sql=" + prepareStatement.toString());
			int col = rs.getMetaData().getColumnCount();
			System.out.println("============================");
			while (rs.next()) {
				for (int i = 1; i <= col; i++) {
					System.out.print(rs.getString(i) + "\t");
					if ((i == 2) && (rs.getString(i).length() < 8)) {
						System.out.print("\t");
					}
				}
				System.out.println("");
			}
			System.out.println("============================");
			rs.close();
			prepareStatement.close();
			connection.close();
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}

	}

}

#用户输入正常合法的值
SELECT * FROM admin WHERE username = '韦小宝' AND `password` = '222';
#用户输入正常合法的值
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '222';

#sql注入(用户输入非法的值)使用Statement对象,无法防止sql注入(会查询出表的所有数据)
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '222' OR '8'='8'
#sql注入(用户输入非法的值)使用PreparedStatement对象,可以有效防止sql注入
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '222\' OR \'8\'=\'8'

#sql注入(用户输入非法的值)使用Statement对象,无法防止sql注入(DROP操作很危险)
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = ''; DROP TABLE tableName;#'
#sql注入(用户输入非法的值)使用PreparedStatement对象,可以有效防止sql注入
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '\'; DROP TABLE tableName;#'

#sql注入(用户输入非法的值)使用Statement对象,无法防止sql注入(TRUNCATE操作很危险)
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = ''; TRUNCATE TABLE tableName;#'
#sql注入(用户输入非法的值)使用PreparedStatement对象,可以有效防止sql注入
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '\'; truncate table tableName;#'

#sql注入(用户输入非法的值)使用Statement对象,无法防止sql注入(DELETE操作很危险)
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = ''; DELETE FROM tableName;#'
#sql注入(用户输入非法的值)使用PreparedStatement对象,可以有效防止sql注入
SELECT * FROM admin WHERE username = '韦小宝' AND PASSWORD = '\'; delete from tableName;#'

#所以生产环境上一定要使用PreparedStatement,而不能使用Statement

/*
顺便复习一下mysql中的3种注释,我是多行注释
*/

#我是单行注释

-- 我也是单行注释(注意:-- 这种注释,后面必须要加一个空格,否则语法报错)


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130163.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 4g融合指的是什么_天翼网关3

    4g融合指的是什么_天翼网关3小草科技推出融合通信新产品系列——多网融合多路聚合今天,深圳小草信息科技有限公司发布了系列新产品,以解决当前移动互联网网络不稳定带宽不够、安全性差等问题。智能融合通信将有线与多路无线智能融合成为一路通道,并聚合多个通道形成一个大容量通道,实现大数据在一个聚合通道中的传输。加载自有协议,安全、快速、稳定的传送数据至云端,提供安全稳定的宽带传输通道,确保业务永不中断。1,MNF-410…

    2022年10月3日
    0
  • 防止网站被挂马_网站被挂马的原因

    防止网站被挂马_网站被挂马的原因今天遇到一个很奇怪的挂马问题,查关键词,查数据库等常规方法都没有找到原因,debug断点都放在了程序执行代码最前面还是输出挂马内容,用php探针发现也有代码,所以确认了是iis全局的问题,所以查加载查组件,最终经过比对是iis被黑添加了模块,被添加的名称很具有迷惑性,通常伪装的很像系统模块,遇到查不到是什么地方挂马,可以放一个探针来判断下是不是iis问题。»转载请保留出处:豫章小站…

    2022年9月29日
    1
  • Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解「建议收藏」

    Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解「建议收藏」首先分四部曲简单做一下说明1.What(是什么):Intent类中的一个静态标志属性publicstaticfinalintFLAG_ACTIVITY_NEW_TASK=0x10000000;2.Why(为什么要使用):在特殊情况下,如果不加这个标志,会报错(下文详细说明)3.When(什么时候使用):当调用startActivity启动一个Activity时4.How(如何

    2022年10月6日
    0
  • 使用opkg update时遇到wget returned 4错误

    使用opkg update时遇到wget returned 4错误环境:OpenWrt虚拟机,NAT网卡,网络连接正常解决办法:先使用wget下载opkgupdate中提示安装失败的安装包,再使用opkgupdate参考资料:SOLVED:FailedtodownloadthepackagelistArcherC7v2withLEDE17.01.0…

    2022年5月30日
    235
  • 深度学习小白实现残差网络resnet18 ——pytorch「建议收藏」

    深度学习小白实现残差网络resnet18 ——pytorch「建议收藏」深度学习小白实现残差网络resnet18——pytorch利用闲暇时间写了resnet18的实现代码,可能存在错误,看官可以给与指正。pytorch中给与了resnet的实现模型,可以供小白调用,这里不赘述方法。下面所有代码的实现都是使用pytorch框架书写,采用python语言。网络上搜索到的resne18的网络结构图如下。resnet18只看图中左侧网络结构就可以。(ps:使用的是简书上一个博主的图,如有冒犯,请谅解)接下来,根据如图的网络结构进行搭建网络。通过观察网络结构,发现在网络结

    2022年5月15日
    54
  • Windows 7专业版安装VS2005与WinCE6.0开发环境

    近期更新了自己的小黑从XP更新到WIN7专业版,我花了两天时间验证了下列软件安装在WIN7PRO是完全兼容的。1:2011年最新更新的SourceInsight3.50.0066版本,这个是支持W

    2021年12月26日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号