Jdbc学习笔记(四)--PreparedStatement对象、sql攻击(安全问题)

目录

(一)使用PreparedStatement对象的原因:

使用Statement对象编写sql语句会遇到的问题

​编辑 (二)sql攻击

1.什么是sql攻击

 2.演示sql攻击

 (三)防止SQL攻击

1.PreparedStatement是什么

2. PreparedStatement的使用

​编辑 3.总结:


(一)使用PreparedStatement对象的原因:

使用Statement对象编写sql语句会遇到的问题

使用Statement对象编写sql语句,都是拼接sql

问题:

  1. 可读性差
  2. 编写复杂,容易出错
  3. 安全问题,sql攻击(sql注入)  最大问题,系统会被攻破

 (二)sql攻击

1.什么是sql攻击

      在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!

 2.演示sql攻击

首先我们需要创建一张用户表,并插入数据,用来存储用户的信息

下面我们写一个login()方法!

public static boolean login(String username, String password) {
    Connection conn=null;
    Statement stmt=null;
    ResultSet rs=null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/esa?useSSL=false","root","123456");
        String sql="select count(1) num from user where username='"+username+"' and password='"+password+"'";
        System.out.println(sql);
        stmt=conn.createStatement();
        rs=stmt.executeQuery(sql);
        rs.next();
        int count=rs.getInt(1);
        return count >= 1;
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    }catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        try{
            if (rs!=null) rs.close();
            if (stmt!=null) stmt.close();
            if (conn!=null) conn.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

细节:

throw new RuntimeException(e);  不能写成e.printStackTrace(),不然会报错,无法运行

e.printStackTrace( )是打印异常栈信息

throw new RuntimeException(e)是把异常包在一个运行时异常中抛出。

因为return count >= 1,系统会无法识别return的是一个什么值,会显示缺少return语句;

下面是调用这个方法的代码:

login("a' or '1'='1", "b' or '1'='1"); 

控制台输出登陆成功,因为是输入的用户名和密码是SQL语句片段,最终与我们的login()方法中的SQL语句组合在一起!我们来看看组合在一起的SQL语句:

select count(1)  from tb_user where username = 'a' or '1'='1' and password='b' or '1'='1'

因为 'a' or '1 = 1'这个语句,or作为关键字只要有一边返回的是true那么这个整体的值就是true,右边始终返回true,所以不管左边是否正确,这个值永远是true,那么就很容易被别人登录进去,从而造成安全问题。

 (三)防止SQL攻击

jdk中提供一个Statement的子接口,java.sql.PreparedStatement

Statement在创建时不需要传sql语句,而是把sql语句拼接起来,发送给mysql服务器

PreparedStatement是预编译的Statement,可以使用占位符?,给值占位

1.PreparedStatement是什么

PreparedStatement叫预编译声明

什么是预编译:在sql语句执行之前,要先进行两个步骤,sql编译和sql语法分析,在语句第一遍执行完毕以后,PreparedStatement会将预编译结果保存下来,在一下遇到相同的sql语句时,就不需要再重新进行一遍这三个步骤,可以跳过前两个,这也是为什么效率提高了的原因

PreparedStatement是Statement的子接口,你可以使用PreparedStatement来替换Statement。

PreparedStatement的好处:

  • 防止SQL攻击;

  • 提高代码的可读性,以可维护性;

  • 提高效率。

2. PreparedStatement的使用

  1. 使用Connection的prepareStatement(String sql):即创建它时就让它与一条SQL模板绑定;

  2. 调用PreparedStatement的setXXX()系列方法为问号设置值

  3. 调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法;

接下来我们来进行演示:

对之前的代码进行修改:

1.将拼接的username和password换成?

2.创建PreparedStatement对象,将Statement改成PreparedStatement

3.因为PreparedStatement的executeQuery()和executeUpdate()方法是无参的,所以要将括号中的sql删除

4.给?赋值

PreparedStatement提供了一组setXxx(int  问号的索引,值)方法,问号索引从1开始

如果不知道列的数据类型,有一个通用数据类型:setObject()

代码: 

public static boolean login2(String username, String password) {
    Connection conn=null;
    PreparedStatement stmt=null;
    ResultSet rs=null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/esa?useSSL=false","root","123456");
        String sql="select count(1) num from tb_user where username = ? and password= ?";
        System.out.println(sql);
        stmt = conn.prepareStatement(sql);
        //----------------
        //给?赋值
        //----------------
        stmt.setString(1,username);
        stmt.setString(2,password);
        rs=stmt.executeQuery();
        rs.next();
        int count=rs.getInt(1);
        return count >= 1;
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    }catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        try{
            if (rs != null) rs.close();
            if (stmt != null) stmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

执行结果:

登录失败!!,防止sql攻击成功

 3.总结:

 所以,建议大家在今后的开发中,无论什么情况,都去需要PreparedStatement,而不是使用Statement。  

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter中的定时器(二)

5--JSR223 Timmer 功能特点 自定义延迟逻辑:使用脚本语言动态计算请求之间的延迟时间。灵活控制:可以根据测试数据和条件动态调整延迟时间。支持多种脚本语言:支持 Groovy、JavaScript、BeanShell 等多种脚本语言。 支持的脚本语言 Groov…

【Istio】Istio原理

第一章 Istio原理 一、服务网格(servicemesh)1、六个时代2、服务网格定义及优缺点二、Istio1、Istio定义2、Istio安装3、Istio架构1.5版本之前1.5版本之后4、bookinfo案例架构部署5、CRD一、服务网格(servicemesh) 微服务:架构风格,职责单一,api通信 服务网格:微服务时代的…

4.远程访问及控制

SSH 简介: SSH(Secure Shell)协议是一种安全通道协议,对通信数据进行了加密处理,用于远程管理。 OpenSSH简介 OpenSSH 服务名称:sshd 服务端主程序:/usr/sbin/sshd 服务端配置文件&#xf…

精通rust宏系列教程-入门篇

Rust最令人敬畏和强大的特性之一是它使用和创建宏的能力。不幸的是,用于创建宏的语法可能相当令人生畏,并且对于新开发人员来说,这些示例可能会令人不知所措。我向你保证Rust宏非常容易理解,本文将为你介绍如何创建自己的宏。 什么…

设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

前言: 两个本想描述一样的意思的词,只因一字只差就让人觉得一个是好牛,一个好搞笑。往往我们去开发编程写代码时也经常将一些不恰当的用法用于业务需求实现中,但却不能意识到。一方面是由于编码不多缺少较大型项目的实践&#xff…

kubernetes简单入门实战

本章将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其访问 Namespace Namespace是k8s系统中一个非常重要的资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。 默认情况下,k8s集群中的所有的Pod都是可以相…

webpack5 + vue3 从零配置项目

前言 虽然在实际项目当中很少会从 0 到 1 配置一个项目,毕竟很多重复工作是没有必要的,脚手架将这些重复性的工作进行了整合,方便开发者使用。也正因如此,导致部分开发者过于依赖脚手架,却不清楚其内部的实现流程&…

Linux git-bash配置

参考资料 命令提示符Windows下的Git Bash配置,提升你的终端操作体验WindowsTerminal添加git-bash 目录 一. git-bash配置1.1 解决中文乱码1.2 修改命令提示符 二. WindowsTerminal配置git-bash2.1 添加git-bash到WindowsTerminal2.2 解决删除时窗口闪烁问题 三. VS…

(RK3566驱动开发 - 1).pinctrl和gpio子系统

一.设备树 pinctrl部分可以参考 rockchip 官方的绑定文档 :kernel/Documentation/devicetree/bindings/pinctrl PIN_BANK:引脚所属的组 - 本次例程使用的是 GPIO3_A1 这个引脚,所以所属的组为 3; PIN_BANK_IDX:引脚的…

基于OpenFOAM和深度学习驱动的流体力学计算与应用

在深度学习与流体力学深度融合的背景下,科研边界不断拓展,创新成果层出不穷。从物理模型融合到复杂流动模拟,从数据驱动研究到流场智能分析,深度学习正以前所未有的力量重塑流体力学领域。近期在Nature和Science杂志上发表的深度学…

uniapp设置tabBar高斯模糊并设置tabBar高度占位

1、设置tabBar高斯模糊 2、设置tabBar高度占位 (1)需要先在App.vue中获取一下 uni.getSystemInfoSync().windowBottom; //返回值是tabBar的高度(2)在全局样式文件/uview-ui/libs/css/style.vue.scss中定义一个全局样式 3、在需…

嵌入式Linux输入系统应用编程学习总结

嵌入式Linux输入系统应用编程学习总结 目录 嵌入式Linux输入系统应用编程学习总结1. 嵌入式Linux输入系统介绍2. Linux设备输入数据的几个结构体2.1 内核中表示一个输入设备的结构体2.2 APP从输入设备获取的数据类型结构体 3. 查看LCD设备信息和输入数据3.1 查看设备信息3.2 使…

力扣=Mysql-3322- 英超积分榜排名 III(中等)

一、题目来源 3322. 英超积分榜排名 III - 力扣(LeetCode) 二、数据表结构 表:SeasonStats --------------------------- | Column Name | Type | --------------------------- | season_id | int | | team_id …

HTML之列表学习记录

练习题&#xff1a; 图所示为一个问卷调查网页&#xff0c;请制作出来。要求&#xff1a;大标题用h1标签&#xff1b;小题目用h3标签&#xff1b;前两个问题使用有序列表&#xff1b;最后一个问题使用无序列表。 代码&#xff1a; <!DOCTYPE html> <html> <he…

【ElasticSearch】定位分片不分配

记录遇到的es集群分片不分配的情况--待补全 定位分片不分配的原因 定位分片不分配的原因 在shell客户端执行如下的语句&#xff1a; curl -X GET "http://192.168.0.209:9200/_cat/shards?v&hindex,shard,prirep,state,unassigned.reason"集群中各分片的状态都…

10款PDF合并工具讲解与推荐!!!

在现在的大环境下&#xff0c;PDF文件因其跨平台、格式固定等优势&#xff0c;成为了我们工作和学习中不可或缺的一部分。是最常用的文档格式之一。然而&#xff0c;面对多个PDF文件需要合并成一个的场景&#xff0c;如何选择一款高效、易用的PDF合并工具就显得尤为重要。今天&…

「QT」窗口类 之 QWidget 窗口基类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制…

【机器学习】如何配置anaconda环境(无脑版)

马上就要上机器学习的实验&#xff0c;这里想写一下我配置机器学习的anaconda环境的二三事 一、首先&#xff0c;下载安装包&#xff1a; Download Now | Anaconda 二、打开安装包&#xff0c;一直点NEXT进行安装 这里要记住你要下载安装的路径在哪&#xff0c;后续配置环境…

【3D Slicer】的小白入门使用指南四

开源解剖影像浏览工具Open Anatomy Browser使用及介绍 和3D slicer米有太大关系,该工具是网页版影像数据的浏览工具(可以简单理解为网页版的3D slicer) 介绍 ● 开放解剖(OA)浏览器是由神经影像分析中心开发的,基于网络浏览器技术构建的图谱查看器。 ● OA浏览器将解剖模…

Unity使用PS合并贴图

前言 使用PBR渲染&#xff0c;金属工作流时&#xff0c;默认使用一个金属度贴图&#xff0c;其中r通道保存金属度&#xff0c;a通道保存光滑度&#xff0c;g通道和b通道没使用&#xff1b; 我们很可能使用Occlusion Map&#xff0c;使用其中的g通道保存Occlusion 信息。单独使用…