什么是SQL注入?基于实例讲解

news2024/11/16 17:38:08

一、SQL注入的含义:

SQL注入是一种常见的网络攻击,由于程序对输入数据的判断或者检验不严格,导致攻击者查询到了授权范围之外的数据,甚至还可以修改数据库中的数据,对数据库执行一些管理操作等,所以它的危害性也是比较大的。

像下面这个SQL,程序的本意是查询id=1的用户信息,但如果输入的参数后面又添加了OR 1=1,这样就会把所有的用户信息搜出来,显然,这是我们需要避免的:

SELECT * FROM t_user WHERE id = 1 OR 1=1;

二、实例演示:

首先创建一个测试表,并插入简单的数据(MySQL数据库):

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `password` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `t_user` VALUES ('1', 'John', '111111');
INSERT INTO `t_user` VALUES ('2', 'Tom', '222222');

接下来是Java程序部分,采用Spring Boot加上MyBatis的方式,如果对于搭建Spring Cloud工程还不太熟悉,可以参考之前的文章:手把手:Spring Cloud Alibaba项目搭建

在pom.xml文件中添加依赖:

<!-- 连接Spring Boot和MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

<!-- mysql 驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

然后是Java各层的代码,从controller一直到dao,为了完整起见,我把代码都贴出来。controller层有一个方法,参数为用户名,返回该用户的详细信息,为了演示方便,此处返回一个列表:

package com.fullstack.commerce.user.controller;

import com.fullstack.commerce.user.entity.User;
import com.fullstack.commerce.user.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("user")
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping("getUserInfo")
    @ResponseBody
    // 根据用户姓名查询出用户列表信息
    public List<User> getUserInfo(@RequestParam("username")String username){
        List<User> result =  userService.getUserInfo(username);
        return result;
    }
}

service层比较简单,有一个接口和对应的实现类,而实现类就是调用dao的方法,把用户列表查询出来:

package com.fullstack.commerce.user.service;

import com.fullstack.commerce.user.entity.User;
import java.util.List;

public interface UserService {
    List<User> getUserInfo(String username);
}
package com.fullstack.commerce.user.service.impl;

import com.fullstack.commerce.user.dao.UserDao;
import com.fullstack.commerce.user.entity.User;
import com.fullstack.commerce.user.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;
    @Override
    public List<User> getUserInfo(String username) {
        return userDao.getUserInfo(username);
    }
}

dao层就是一个接口,里面只有一个方法:

package com.fullstack.commerce.user.dao;

import com.fullstack.commerce.user.entity.User;
import java.util.List;

public interface UserDao {
    List<User> getUserInfo(String username);
}

除了上面的业务代码,还需要有一个启动类:

package com.fullstack.commerce.user;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = "com.fullstack.commerce.user.dao")
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

以下是对应的mapper文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fullstack.commerce.user.dao.UserDao">
    <resultMap id="UserMap" type="com.fullstack.commerce.user.entity.User">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
    </resultMap>

    <select id="getUserInfo" resultMap="UserMap">
        SELECT * FROM t_user WHERE username = ${username}
    </select>
</mapper>

注意,在上面这个mapper文件中,只有一个select语句,而这个语句传参使用了符号$,它会把参数值直接进行替换,而不会进行预编译(如果使用占位符#,就会进行预编译,从而可以防止SQL注入)。

当然,application.yml文件也需要配置一下,数据库用户名和密码替换成实际的:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: myuser 
    password: myuser
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: mapper/*.xml

代码就算写完了,接下来我们测试一下看看。

三、测试验证:

启动程序,我们来进行测试,在浏览器里面输入以下地址,然后回车:

http://localhost:8080/user/getUserInfo?username='John'

没问题,我们是要查找用户名为John的数据,它返回了如下的结果,正是我们所期望的:

图片

但如果我们把参数重新设置一下,变成如下这样:

http://localhost:8080/user/getUserInfo?username='John' OR 1=1

那就相当于在数据库中执行下面的SQL了,也就是返回所有的用户数据:

SELECT * FROM t_user WHERE username = 'John' OR 1=1

看结果,确实是这样,把表中的两条记录都返回到了客户端(测试数据只插了两条记录,如果有多条,同样会把所有的数据都返回过来):

图片

这显然是不对的,接口把查询范围之外的数据都搜索出来了,如果还有一些修改数据或者操纵数据库的一些命令,那就更危险了。

当然,我们把mapper文件里面的参数部分改成占位符#,这样就会先进行预编译,就不会发生刚才的情况了。修改成#以后运行程序,再执行上面的url,就会返回空了,因为这个时候是去数据库中查询用户名为【'John' OR 1=1】的记录,显然是不存在的。

四、总结:

SQL注入是比较常见的一种攻击方式,如果ORM框架选择了MyBatis,处理这种问题的方式也相对比较简单,就是对于参数的处理要使用占位符,而不是直接把用户的输入进行简单的拼接。

本文主要是介绍SQL注入的基本概念,并用实际的例子来进行演示,以便让朋友们有一个直观的入门认识。在实际情况中,SQL注入细分也有很多的类型,而完善的处理方式也包括controller层的输入检验等,甚至api网关或者反向代理也需要考虑这样的情况,此处不再深入。

鸣谢:

https://www.geeksforgeeks.org/sql-injection/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Material-UI】Button 中的点击事件处理(Handling clicks)详解

文章目录 一、点击事件处理基础1. 基本用法2. 事件处理器的传递 二、实际应用中的注意事项1. 事件处理逻辑的优化2. 避免过多的状态更新3. 使用合适的事件类型 三、关于文档中未提及的原生属性四、最佳实践1. 无障碍性2. 视觉反馈3. 防止重复点击 五、总结 在现代前端开发中&am…

测试TLP 使用外部 50Ω 电缆和非 50Ω 电缆影响

测试目的 实验有 SMA 母头连接器与没有SMA母头连接器 I/V 曲线的影响实验 50Ω 电缆和非 50Ω 电缆应用条件下的 I/V 曲线研究初始启动和 16A DUT(被测器件)应用条件下的脉冲电压和脉冲电流影响 开始测试前先做短路/开路校正 短路校正 开路校正 TLP取样方式与为框黄色70ns~90…

详解线程池的使用

一、线程池基础 1.1、线程池的思想 我们首先理解什么是池化技术&#xff1a; 池化技术指的是提前准备一些资源&#xff0c;在需要时可以重复使用这些预先准备的资源。 池化技术的优点主要有两个&#xff1a;提前准备和重复利用。 下面是池化技术常见的应用场景&#xff1a; …

SpringBoot+Redis 发布与订阅

两个应用都引入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artif…

机器学习入门之无监督学习(聚类、降维(主成分分析)、关联度分析(Apriori 算法))

无监督学习是机器学习的一种类型&#xff0c;它处理没有显式标签的数据。与监督学习不同&#xff0c;无监督学习的目标是探索数据的内在结构和模式&#xff0c;而不是从标注数据中学习一个特定的映射到预定标签的函数。这使得无监督学习特别适用于探索性数据分析、找寻隐藏模式…

关于加载水印PDF、图片以及压缩包格式文件【把博客当工作记录】

写这篇文章的目的是让大家都可以学到东西,核心代码中列出了处理思维和调用方法,业务代码已经过滤掉了,希望大家不要做crud程序员!!要思考。。。该博客不懂时可联系下方。 1、流程图如下 2、策略描述 实现方式: 设计模式:父策略调动子策略 业务理念:在不影响原有业务…

【电脑基础硬件】从零开始认识主板

从零开始认识主板 一、主板及其元器件二、主板上的各个部件通信三、主板的选择 注意&#xff1a; 以下以Z790电脑主板为例进行说明。 一、主板及其元器件 IO接口&#xff1a; CPU模块 CPU是电脑的大脑&#xff0c;控制并指挥着电脑的各个模块协同工作。CPU通过主板上的插槽固定…

电路中电阻,电容和电感作用总结

电阻作用 1&#xff0c;上拉电阻 电阻的连接一般是一端接上拉的电源&#xff08;一般与芯片信号的电压值相匹配&#xff09;&#xff0c;另一端连接芯片引脚所对应的信号大概如下图 功能&#xff1a;一、预置某些引脚的功能&#xff0c;例如复位信号拉高&#xff08;失能&…

疯传!平台培养“斗士”的背后,是 AI 智能名片与 O2O 商城小程序在搞鬼

摘要&#xff1a;本文探讨了在搭建用户聚集平台以筛选和培养“斗士”的过程中&#xff0c;如何融入 AI 智能名片和 O2O 商城小程序。详细阐述了贴吧或论坛作为初始平台的优势&#xff0c;以及如何通过适当的管理和引导活动筛选出“储备斗士”。同时&#xff0c;分析了 AI 智能名…

浅谈 Mybatis 框架

文章目录 一、什么是MyBatis?1.2、JDBC 二、使用Mybatis2.1、配置MyBatis开发环境2.1.1、配置连接字符串2.1.2、配置MyBatis中的XML路径 2.2、使用MyBatis模式和语法操作数据库 三、使用 Mybatis 进行增删改查操作的要点3.1、ResultMap的用法 四、Mybatis操作难点4.1、#{ } 和…

Modbus-TCP详解

目录 Modbus-TCP Modbus TCP协议的帧结构如下&#xff1a; 实现Modbus-Tcp 使用EasyModbusTCP第三方实现Modbus-Tcp EasyModbusTCP的使用 设置IP 设置端口 设置设备地址 开启通讯 读取寄存器 写入寄存器 实例 Modbus-TCP Modbus TCP是Modbus协议的一种变体&#xff0c;它使用T…

Java多线程的单例设计模式 多种实现方法

目录 前言 饿汉式 懒汉式 Double_check volatile double_check Holder方式 枚举 前言 单例设计模式GOF23中设计模式中最常用的设计模式之一, 单例设计模式提供了多线程环境下的保证唯一实例性的解决方案, 虽然简单, 但是实现单例模式的方式多种多样, 因此需要从多个维度去…

【云原生】恰当运用kubernetes中三种探针,确保应用程序在Kubernetes集群中保持健康、可用和可靠

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Unity热更——ILRuntime安装接入

一、ILRuntime相关地址 1、官网文档地址 2、GitHub上开源的ILRuntime项目工程 3、GitHub上的官方ILRuntime-Unity实例工程 4、官方视频教程-Unity中文课堂&#xff08;需付费&#xff09; 5、ILRuntime入门笔记-赵青青-博客园 6、ILRuntime 的学习-简书 二、ILRuntime…

Python | Leetcode Python题解之第324题摆动排序II

题目&#xff1a; 题解&#xff1a; def quickSelect(a: List[int], k: int) -> int:seed(datetime.datetime.now())shuffle(a)l, r 0, len(a) - 1while l < r:pivot a[l]i, j l, r 1while True:i 1while i < r and a[i] < pivot:i 1j - 1while j > l an…

自动生成数据:Navicat 16 让数据测试更高效

文章目录 前言一、Navicat是什么&#xff1f;二、Navicat 16 新功能1. 自动生成数据2. 改进的用户界面3. 云同步 三、 安装指南Windows 版安装macOS 版安装Linux 版安装 四、使用示例&#xff1a;自动生成数据1. 创建连接2. 选择表3. 打开数据生成器4. 设置数据规则5. 生成数据…

top命令实时监测Linux进程

top命令可以动态实时显示Linux进程信息&#xff0c;方便观察频繁换进换出的内存的进程变化。 top命令执行示例如下&#xff1a; 其中&#xff0c;第一行表示系统当前时间、系统的运行时间、登录的用户数目、系统的平均负载&#xff08;最近1分钟&#xff0c;最近5分钟&#xff…

springboot艺体培训机构业务管理系统--论文源码调试讲解

第2章 开发环境与技术 开发艺体培训机构业务管理系统需要搭建编程的环境&#xff0c;也需要通过调查&#xff0c;对各个相关技术进行分析&#xff0c;选取适合本系统开发的技术与工具。 2.1 MySQL数据库 MySQL是一种具有安全系数、安全系数、混合开发性、高效化等特征的轻量…

基于Raft算法的分布式KV数据库:五、剩余部分

github地址&#xff1a;https://github.com/1412771048/Raft CPPRaft系列-剩余部分 首先我们看下第五章的架构图&#xff0c;图中的主要部分我们在前几张讲解完毕了&#xff0c;目前还剩下clerk和k-v数据库&#xff0c;而本篇的重点在于补全版图&#xff0c;完成&#xff1a;…

SQL注入sqli-labs-master关卡一

本文环境搭建使用的是小皮&#xff0c;靶机压缩包&#xff1a;通过百度网盘分享的文件&#xff1a;sqli-labs-php7-master.zip 链接&#xff1a;https://pan.baidu.com/s/1xBfsi2lyrA1QgUWycRsHeQ?pwdqwer 提取码&#xff1a;qwer 下载解压至phpstudy的WWW目录下即可。 第一…