序列化和反序列化(一)

          因为通过这段时间的学习,发现,序列化和反序列化的考点和漏洞在平时遇到的还是比较多的,而且自己也没有特别去学习过这个知识点,所以在这里写一篇关于这里序列化和反序列话的博客,废话就停止在这里了。

        在介绍具体的序列化和反序列化基础之前,因为没有系统性地整理过php的知识点,所以还是选择整理一下php的一些基础知识点

php面向对象基本概念、类与对象

一.面向对象

        (一)基本介绍

        面向对象(Object-Oriented,简称 OO)是一种编程思想和方法,它将程序中的数据和操作数据的方法封装在一起,形成"对象",并通过对象之间的交互和消息传递来完成程序的功能。

        在面向对象的程序设计(英语:Object-oriented programming,缩写:OOP)中,对象是一个由信息及对信息进行处理的描述所组成的整体,是对现实世界的抽象。举个例子,在现实世界里我们所面对的事情都是对象,如计算机、电视机、自行车等。

PHP 面向对象 | 菜鸟教程

        面向对象编程强调数据的封装、继承、多态和动态绑定等特性,使得程序具有更好的可扩展性、可维护性和可重用性。

        (二)面向对象编程三大特征:封装、继承、多态

1、封装:将对象的属性和行为封装起来,将对象的属性和行为封装起来的载体就是类
2、继承:继承性是子类自动共享父类数据结构和方法的机制,是类之间的一种关系;当处理一个问题时,可以将一些有用的类保留下来,这些类通常有相同的属性甚至相同的方法,当遇到同样的问题时可以拿来复用

父类:一个类被其它类继承,可将该类成为父类;

子类:一个类继承其他类称为子类(派生类);
3、多态:将父类对象应用于子类的特征就是多态。子类继承了父类的特点,同时子类又有自己的特点即是多态,多态指的是一个类的实例(对象)可以表现出多种形态。

二.面向过程

        面向过程是一种以“整体事件”为中心的编程思想,编程的时候把解决问题的步骤分析处理,然后用函数把这些步骤实现,再一步步的具体步骤中再按顺序调用函数

三.类

        (一)定义(类和对象的关系)

        类定义了一件事的特点,将数据的形式以及这些数据上的操作封装在一起;对象是具有类类型的变量,是对类的实例;类是想法,把类实例化,调用具体值后就变成对象。

        举个例子

class Zerotwo
{
    //类体:由成员函数(方法)和成员变量(属性)组成
    //成员变量声明
    //成员函数声明
   
}

        在这个例子里面:

        class为定义类的关键字,Zerotwo为类的名字,{}中为类的主体

        类体中的内容为类的成员;

        类中的变量称为成员变量(属性):定义再类内部的变量,该变量的值对外是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可成为对象的属性;

        类中的函数称为成员函数(方法):定义在类的内部,可用于访问对象的数据。

        (二)类的内容    

1.预定义      
class Zerotwo
{
    var $name;    //声明成员变量,var是一种修饰符
    var $sexl;    
    function state($var1)    //声明成员函数(方法)
    {
        echo $this->name;    //使用预定义$this调用成员变量
        echo $var1;    //成员函数传参$var1可直接调用
    }
}

        运行结果可见,实际上这个定义了以后,因为只是定义好了类和类体,语言类型等等关键信息都没有加上,所以会被编译器自动识别,然后直接输出。那么接下来我们就要将这个类实例化和赋值

2、实例化和赋值
<?php
class Zerotwo
{
    var $Darling;    //声明成员变量,var是一种修饰符
    var $Franxx;
    function state($var1)    //声明成员函数(方法)
    {
        echo $this->Darling;    //使用预定义$this调用成员变量
        echo $var1;    //成员函数传参$var1可直接调用
    }
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
$zzc->Darling = '02,02,02';    //参数赋值
$zzc->Franxx = 'guojiadui';
print_r($zzc);    //打印对象

?>

        那么这里的运行结果就不一样很多了,从运行结果可以看见这里的类Zerotwo被实例化了,并且被对象zzc赋值了

        再演示一个不指向的

<?php
class Zerotwo
{
    var $Darling;    //声明成员变量,var是一种修饰符
    var $Franxx;
    function state($var1)    //声明成员函数(方法)
    {
        echo $this->Darling;    //使用预定义$this调用成员变量
        echo '关于'.$var1;    //成员函数传参$var1可直接调用
    }
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象lin
$zzc->Darling = '02';    //参数赋值
$zzc->state('国家队');//调用函数

?>

运行结果

 

3、类的访问权限修饰符

        PHP 支持三种访问修饰符:publicprotected 以及 private,这些修饰符所提供的访问级别具体如下。

public:公共的,在类的内部、子类中 或者类的外部都可以使用,不受限制;

protected:受保护的,在类的内部、子类中可以使用,但不能在类的外部使用;

private:私有的,只能在类的内部使用,在类的外部或者子类中无法使用。

        上图:

还是用刚刚的代码的例子

        外部

<?php
class Zerotwo
{
    public $Franxx = '国家队';    //声明成员变量,var是一种修饰符
    private $Darling = '02';
    protected $zerotwo = '比翼鸟';
    function state($var1)    //声明成员函数(方法)
    {
        echo $this->Darling;    //使用预定义$this调用成员变量
        echo $var1;    //成员函数传参$var1可直接调用
    }
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
echo $zzc->Franxx;    //外部可用
echo $zzc->Darling;   //外部不可用
echo $zzc->zerotwo;   //外部不可用

?>

        运行结果如下

        这里的代码是会报错的,因为违背了封装原则,这里尝试通过 $zzc->Darling 和 $zzc->zerotwo 在类的外部访问私有和受保护属性,就会导致错误,但是这个错误在这里无伤大雅,会在子类那边出错。

        子类

        再次修改代码进行访问

<?php
class Zerotwo       //父类
{
    public $Franxx = '国家队';    //声明成员变量,var是一种修饰符
    private $Darling = '02';
    protected $zerotwo = '比翼鸟';
    function state($var1)    //声明成员函数(方法)
    {
        echo $this->Darling;    //使用预定义$this调用成员变量
        echo $var1;    //成员函数传参$var1可直接调用
    }
}
class Zerotwo2 extends Zerotwo       //子类
{
    function test()
    {
        echo $this->Darling."<br />";       //private子类不可用
        echo $this->zerotwo."<br />";       //protected子类可用
        echo $this->Franxx."<br/>";        //public子类可以用
    }
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
$zzc2 = new Zerotwo2();
echo $zzc->Franxx."<br />";    //外部可用
echo $zzc->Darling;   //外部不可用
echo $zzc2->test();

?>

分析

        (这里的"<br />"是html语言的换行,php编译器是无法识别的,只会将它作为字符串输出,php语言的换行可见下面的代码)

        这个时候会发现,出错了 ,这个结果并没有像编译的代码一样输出“$zzc2->test();”的内容,这里的原因是因为在 PHP 中,访问私有属性时,如果尝试从类的外部或从子类访问一个私有属性,会导致一个致命错误(Fatal Error)。这种错误会立即停止脚本的执行,因此任何后续的代码,包括 $zzc2->test();,都不会被执行。这里也是为了演示一下,如果强行去访问私有属性会带来的后果。

        修改以后的代码

<?php
class Zerotwo       //父类
{
    public $Franxx = '国家队';    // 公有成员变量
    private $Darling = '02';      // 私有成员变量
    protected $zerotwo = '比翼鸟'; // 受保护成员变量

    function state($var1)    // 声明成员函数
    {
        echo $this->Darling;    // 使用 $this 调用成员变量
        echo $var1;    // 成员函数传参 $var1 可直接调用
    }
}

class Zerotwo2 extends Zerotwo       //子类
{
    function test()
    {
        // echo $this->Darling."<br />"; // 不能访问私有属性,需移除或通过方法访问
        echo $this->zerotwo . PHP_EOL;  // 受保护成员变量,子类可用
        echo $this->Franxx . PHP_EOL;   // 公有成员变量,子类可用
    }
}

$zzc = new Zerotwo();    // 实例化类 Zerotwo() 为对象 $zzc
$zzc2 = new Zerotwo2();

echo $zzc->Franxx . PHP_EOL;    // 外部可用
// echo $zzc->Darling;   // 外部不可用,需移除或通过方法访问
$zzc2->test();
?>

(这里的PHP_EOL就是php语言中的换行)

        这里下面的两个输出就是由对象zzc2控制的。

        那问题又来了,要怎么去访问私有属性呢?还是在原代码的基础上进行修改。

<?php
class Zerotwo       //父类
{
    public $Franxx = '国家队';
    private $Darling = '02';   //定义了私有成员
    protected $zerotwo = '比翼鸟';
    function state($var1)    // 声明成员函数
    {
        echo $this->Darling;    // 使用 $this 调用成员变量
        echo $var1;    // 成员函数传参 $var1 可直接调用
    }
    private function test2()    //定义私有成员的方法
    {
        echo $this->Darling;     //在类的内部访问私有成员变量
    }
    function test3()            //在类的内部访问私有成员的方法
    {
        $this->test2();
    }
}

class Zerotwo2 extends Zerotwo       //子类
{
    function test()
    {
        // echo $this->Darling; // 私有属性,子类不可用
        echo $this->zerotwo . PHP_EOL;  // 受保护成员变量,子类可用
        echo $this->Franxx . PHP_EOL;   // 公有成员变量,子类可用
    }
}

$zzc = new Zerotwo();    // 实例化类 Zerotwo() 为对象 $zzc
$zzc2 = new Zerotwo2();

echo $zzc->Franxx . PHP_EOL;    // 外部可用
//echo $zzc->Darling;   // 外部不可用,需移除或通过方法访问

$zzc2->test();

$zzc ->test3();     //通过在类的外部访问Zerotwo中的公有成员,间接访问Zerotwo中的私有成员
                    //私有成员变量无法直接从定义它的类的外部及该类的子类中直接访问
?>

        通过这种间接访问的方法,就可以访问到这个私有成员了

        这里就不再过多进行实验了,给出关于这个访问修饰符的文章

闪耀的钥匙:PHP 与访问修饰符_php访问修饰符-CSDN博客

序列化基础知识

        一.PHP序列化:serialize()

        序列化:是将变量或对象转换成字符串的过程( 序列化只作用于对象,不序列化方法),用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构。

        简单而言       

序列化:将对象的状态信息(属性)转换为可以存储或传输的形式的过程

对象/数组\rightarrow字符串

在php中使用函数serialize()将对象或者数组进行序列化,并返回一个包含字节流的字符串来表示。

        php序列化的字母标识:

a - 数组 (Array): 一种数据结构,可以存储多个相同类型的元素。
b - 布尔型 (Boolean): 一种数据类型,只有两个可能的值:true 或 false。
d - 双精度浮点数 (Double): 一种数据类型,用于存储双精度浮点数值。
i - 整型 (Integer): 一种数据类型,用于存储整数值。
o - 普通对象 (Common Object): 一个通用的对象类型,它可以是任何类的实例。
r - 引用 (Reference): 指向对象的引用,而不是对象本身。
s - 字符串 (String): 一种数据类型,用于存储文本数据。
C - 自定义对象 (Custom Object): 指由开发者定义的特定类的实例。
O - 类 (Class): 在面向对象编程中,类是一种蓝图或模板,用于创建对象。
N - 空 (Null): 在许多编程语言中,null 表示一个不指向任何对象的特殊值。
R - 指针引用 (Pointer Reference): 一个指针变量,其值为另一个变量的地址。
U - 统一码字符串 (Unicode String): 一种数据类型,用于存储包含各种字符编码的文本数据。

         各类型值的serialize序列化:

空字符       null  ->     N;
整型         123   ->     i:123;
浮点型       1.5   ->     d:1.5;
boolean型    true   ->    b:1;
boolean型    fal    ->    b:0;
字符串       “haha”  ->   s:4:"haha";

         测试一下看看

        (一)对象序列化
<?php
 class Zerotwo                       //定义了一个test类
 {
     public $Franxx = 11;
     private $Darling = aa;
     protected $Zerotwo = true;
     public function zerotwo()
     {
         echo $this->Franxx;
     }
 }
 $zzc = new Zerotwo();            //将test这个类实例化
 echo serialize($zzc);            //序列化对象zzc

        在这里的输出结果中:(11是公有成员输出的值)

  1. O: 这是一个标识符,表示接下来的数据是一个对象(O
  2. 7:"Zerotwo": 这表示对象的类名是 Zerotwo,并且类名包含 7 个字符(实际上应该是 8 个字符,包括引号内的内容)。

  3. :3:: 这表示对象有 3 个属性。

  4. {...}: 花括号内包含了对象的属性和它们的值。

    • s:6:"Franxx";i:11;:

      • s:6:"Franxx": 表示一个字符串属性名 Franxx,该字符串有 6 个字符。
      • i:11: 表示属性值是一个整数 11
    • s:16:" Zerotwo Darling";s:2:"aa";:

      • s:16:" Zerotwo Darling": 表示一个字符串属性名  Zerotwo Darling,该字符串有 16 个字符(注意前面的空格)。
      • s:2:"aa": 表示属性值是一个字符串 aa,该字符串有 2 个字符。
    • s:10:" * Zerotwo";b:1;:

      • s:10:" * Zerotwo": 表示一个字符串属性名  * Zerotwo,该字符串有 10 个字符(注意前面的空格和星号)。
      • b:1: 表示属性值是一个布尔值 true(在序列化中,布尔值 true 被表示为 1false 被表示为 0)。

           同时,需要注意的是,protected 和private输出时有不可打印字符,如下图

         所以在构造payload的时候,会使用urlencode函数,来实现构造

        这里还有补充的一个小点是序列化的格式

序列化格式

  • 私有属性(private): 私有属性在序列化时,属性名会被格式化为 "\0类名\0属性名",以确保在反序列化时仍然能识别出这是一个私有属性,并且属于哪个类。
  • 受保护属性(protected): 受保护属性在序列化时,属性名会被格式化为 "\0*\0属性名",其中 * 表示受保护属性。
  • 公有属性(public): 公有属性在序列化时,属性名不会有特殊前缀,直接使用属性名。

这种序列化格式确保了在序列化和反序列化过程中,属性的可见性和所属类信息不会丢失。

        (二)成员属性调用对象

<?php
class Zerotwo
{
    var $zzc='zhu';
    function  test()
    {
        echo $this->zzc;

    }
}

class Zerotwo2
{
    var $abc;
    function  __construct()         //使用了__construct魔术方法构造函数
    {
        $this->abc=new Zerotwo();
    }

}

$a = new Zerotwo2();
echo serialize($a);

       

         在这个例子中,实例化的对象$a的成员变量‘abc’调用实例化后的对象Zerotwo()

        (三)pop链序列化

           面向属性编程POP( Property Oriented Programming)

POP链就是利用魔法方法在里面进行多次跳转然后获取敏感数据的一种payload

<?php
class Zerotwo
{
    public $a="11";
    public $b=true;
    public $c=0202;
}
class Zerotwo2
{
    public $d;
    public $e="zzczzc";
}

$m=new Zerotwo();
$n=new Zerotwo2();
$n->f=$m;
echo serialize($n);


 

        代码中,$n->f = $m;这一行是将$m对象赋值给$n对象的新属性$f。这里,$f动态创建的,并不是在Zerotwo2类的定义中显式声明的。这里m的值被嵌套在了n里面

(四)数组序列化

<?php
$zzc=array("zerotwo",0202,false);
echo serialize($zzc);

        这里的a表示这是一个数组的序列化(上面的内容有提到),成员属性名为数组的下标,格式 {i:数组下标;类型:长度:“值”; 以此类推}

二.PHP反序列化(unserialize)        

(一)反序列化的特性

1.反序列化之后的内容为一个对象;

2.反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关;

3.反序列化不触发类的成员方法;需要调用方法后才能触发

  (二)反序列化的作用

反序列化:将序列化后的参数还原成实例化的对象。

字符串\rightarrow对象

(三)例子演示    

<?php
class Zerotwo
{
    public $Franxx = 'zzc';
    private $Darling = 0202;
    protected $zerotwo = true;
    public function displayVar()
    {
        echo $this->Franxx;
    }
}
$d=new Zerotwo();
$b=serialize($d);
print_r(unserialize($b));

$a='O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';//反序列化生成的对象的成员属性值由被反序列化的字符串决定,与原来类预定义的值无关
$c=unserialize($a);    //$c把字符串$b反序列化为对象
var_dump($c);        //var_dump()用于打印变量的相关信息,包括变量的类型,值,长度等

     在这个例子中,可以发现的是,反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关。为了方便观察,我将一开始预定义里面的值也打印出来了。

<?php
class Zerotwo
{
    public  $Franxx = 'zzc';
    protected $Darling = 0202;
    private  $zerotwo = true;
    public function displayVar()
    {
        echo $this->Franxx;         //这里没有被调用
    }
}
$d = 'O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';
$a = urldecode($d);
$c = unserialize($a);
$c->displayVar();

        在这个例子中,反序列化不触发类的成员方法;需要调用方法后才能触发

$d = 'O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';
$a = urldecode($d);
$c = unserialize($a);

        这段代码将字符串反序列化为一个 Zerotwo 类的对象 $c。但是,反序列化过程并不会调用 Zerotwo 类中的任何方法。只有当显式调用 $c->displayVar() 方法时,displayVar 方法中的代码才会被执行。

$c->displayVar();

         在这个方法中,echo $this->Franxx; 会输出 Franxx 属性的值。在反序列化后的对象中,Franxx 的值被设置为 123123123,因此调用 displayVar 方法将输出 123123123

(四)反序列化漏洞(简单介绍扩展一下)

1.PHP反序列化漏洞成因

        通过上面的代码,可知在反序列化过程中,unserialize()接收的值(字符串)可控;通过改变这个值(字符串),得到所需要的代码,即生成的对象的属性值。

        通过调用方法,触发代码执行。简单来讲,大概就是一种允许攻击者通过将恶意数据反序列化为PHP对象来执行任意代码的漏洞,我现在的理解是这样的。

2. PHP反序列化工作原理

        PHP反序列化是一种将存储在字符串中的PHP对象转换为PHP变量的过程。这可以通过使用unserialize()函数来实现。

unserialize()函数:将字符串中的数据解析为一个PHP对象,并将其分配给一个变量。

3.PHP 反序列化漏洞的常见方法

(1)反弹 Shell。 这是一种在远程计算机上执行命令的方法。可以通过使用 exec() 或 system() 等函数来完成。
(2)文件上传。 这是一种将文件上传到远程计算机的方法。可以通过使用 move_uploaded_file() 函数来完成。
(3)本地文件包含。 这是一个在远程计算机上包含本地文件的方法。可以通过使用 include() 或 require() 等函数来完成。
(4)数据库访问。 这是一个访问远程计算机上的数据库的方法。可以通过使用 mysql_connect() 或 mysqli_connect() 等函数来完成。

4.防御PHP反序列化漏洞

(1)使用最新版本的 PHP。 最新版本的 PHP 通常包含针对已知漏洞的修复程序。
(2)禁用反序列化。 可以通过在 php.ini 文件中设置 unserialize_callback_func 选项来禁用反序列化。
(3)验证用户输入。 在对用户输入进行反序列化之前,请务必对其进行验证。
(4)使用白名单。 仅允许反序列化来自受信任来源的字符串。
(5)使用签名。 在序列化字符串之前,请使用签名对其进行签名。这将有助于防止恶意字符串被反序列化。

(五)魔术方法

        魔术方法是一个预定好的、在特定情况下自动触发的行为方法。(触发前提:魔术方法所在的类被调用

__construct 当一个对象创建时被调用,

__destruct 当一个对象销毁时被调用,

__toString 当一个对象被当作一个字符串被调用。

__wakeup() 使用unserialize时触发

__sleep() 使用serialize时触发

__destruct() 对象被销毁时触发

__call() 对不存在的方法或者不可访问的方法进行调用就自动调用

__callStatic() 在静态上下文中调用不可访问的方法时触发

__get() 用于从不可访问的属性读取数据

__set() 在给不可访问的(protected或者private)或者不存在的属性赋值的时候,会被调用

__isset() 在不可访问的属性上调用isset()或empty()触发

__unset() 在不可访问的属性上使用unset()时触发

__toString() 把类当作字符串使用时触发,返回值需要为字符串

__invoke() 当脚本尝试将对象调用为函数时触发

__clone() 使用clone关键字拷贝完一个对象后触发
......

还是来一波实操

1.对象被创建时触发__construct()方法,对象使用完被销毁时触发__destruct()方法
<?php
class Zerotwo
{
    public $Darling = "02";
    public  function __construct()
    {
        echo "创建成功----";

    }
    public function __destruct()
    {
        echo "销毁成功";
    }
}

$Darling = new Zerotwo();

        实例化test类为对象赋值给a时就被触发。

2.对象被序列化时触发__sleep(),字符串被反序列化时触发__wakeup()
<?php
class Zerotwo
{
    public $Darling = "02";
    public  function __sleep()
    {
        echo "使用了serialize()----";
        return array("Darling");
    }
    public function __wakeup()
    {
        echo "使用unserialize";
    }
}

$Darling = new Zerotwo();
$Franxx=serialize($Darling);
$zerotwo=unserialize($Franxx);

3.echo $a对象当成字符串输出触发__toString(),$a() 对象当成函数执行触发__invoke()
<?php
class Zerotwo
{
    public $Darling = "02";
    public  function __toString()
    {
        return "字符串----";

    }
    public function __invoke()
    {
        echo "函数";
    }
}

$Darling = new Zerotwo();
echo $Darling;
$Darling ();

 4.$a->callxxx()  调用了不存在的方法 触发__call()方法
<?php
class Zerotwo
{
    public function __call($Franxx,$Darling)
    {
        echo "鸡鸣寺的樱花开了";

    }
}
$Franxx = new Zerotwo();
$Franxx->callxxx();

$a::callxxx() 静态调用 或 调用成员常量时使用不存在的方法,触发 __callStatic()方法
<?php
class Zerotwo
{
    public function __callStatic($Franxx,$Darling)
    {
        echo "$Franxx";

    }
}
$Franxx = new Zerotwo();
$Franxx::callxxx();

5.调用成员属性不存在时触发__get()方法       
<?php
class Zerotwo
{
    public $Darling;
    public  function __get($Darling)
    {
        echo $Darling;

    }
}

$zerotwo= new Zerotwo();
$zerotwo->Franxx;
 6.给不存在的成员属性赋值时触发__set()方法
<?php
class Zerotwo
{
    public $Darling;
    public  function __set($Darling,$Franxx)
    {
        echo "$Franxx,$Darling";

    }
}

$zerotwo= new Zerotwo();
$zerotwo->zzc=0202;

传参$Franxx,$Darling,返回不存在的成员属性名称及其值

        这里特意换了一下位置看看

7.对不可调用的属性使用isset()或empty()时,isset()会被调用
   对不可调用的属性使用unset()时,unset()会被调用

传参$Darling,返回不存在的成员属性名称

<?php
class Zerotwo
{
    protected $Darling;
    public  function __isset($Darling)
    {
        echo "$Darling";

    }
}

$zerotwo= new Zerotwo();
isset($zerotwo->Darling);

<?php
class Zerotwo
{
    protected $Darling;
    public  function __unset($Darling)
    {
        echo "$Darling";

    }
}

$zerotwo= new Zerotwo();
unset($zerotwo->DarlingDarling);

8.使用clone拷贝完成一个对象后,新对象会自动调用__clone()方法 
<?php
class Zerotwo
{
    public $Darling='0202';
    public function __clone()
    {
        echo "调用了__clone()";
    }
}
$zerotwo=new Zerotwo();
$Franxx=clone($zerotwo);

__wakeup()函数漏洞原理:(反序列化漏洞CVE-2016-7124)

当序列化字符串表示对象属性个数的值 大于 真实个数的属性时就会跳过__wakeup的执行

正则匹配大写字母O后不能跟数字时,可在数字前加+号绕过

 

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

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

相关文章

优雅草央千澈-关于蓝湖如何快速的标注交互原型是如何使用的-如何使用蓝湖设计交互原型和整个软件项目的流程逻辑-实践项目详细说明

优雅草央千澈-关于蓝湖如何快速的标注交互原型是如何使用的-如何使用蓝湖设计交互原型和整个软件项目的流程逻辑-实践项目详细说明 问题背景 我们ui设计师在设计完整套ui的时候一般要标注原型&#xff0c;但是如果ui对项目整体理解不够深刻的时候&#xff0c;一般就产品经理需要…

三维测量与建模笔记 - 7.3 表面建模概念和方法

基本概念 当我们通过3D扫描设备对物体进行扫描后&#xff0c;会得到三维点云&#xff0c;通过表面建模&#xff0c;我们会重建出物体的3D模型。如果想得到完整的物体的3D模型&#xff0c;需要对物体进行多个角度的扫描并通过拼接算法重建。经过处理得到的3D模型&#xff0c;在很…

共模电感的工作原理

共模电感也称为共模扼流线圈&#xff0c;是一种抑制共模干扰的器件&#xff0c;它是由两个尺寸相同&#xff0c;匝数相同的线圈对称地绕制在同一个铁氧体环形磁芯上&#xff0c;形成的一个四端器件。当共模电流流过共模电感时&#xff0c;磁芯上的两个线圈产生的磁通相互叠加&a…

汉塔科技-上网行为管理系统 ping.php 远程命令执行漏洞复现

0x01 产品简介 汉塔科技是一家专注于网络应用软件开发的公司,在网络安全、网络协议分析以及网络数据流控制等领域拥有丰富的经验和雄厚的技术实力。其上网行为管理系统是应用识别丰富、网络安全防护强大的专业设备之一,汉塔科技上网行为管理系统是一款功能强大、应用识别丰富…

图书管理系统5,制作第十天

1. 在Java中&#xff0c;BigDecimal 类提供了多种方法可以用来将其转换为 String 类型。以下是几种常见的方法&#xff1a; 使用 toString() 方法&#xff1a; 这是将 BigDecimal 转换为 String 的最直接的方法。 Java 深色版本 BigDecimal bd new BigDecimal("123.456&…

机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差

注&#xff1a;本文为 “keyence 视觉沙龙中机器视觉检测基础知识” 文章合辑。 机器视觉检测基础知识&#xff08;一&#xff09;颜色篇 视觉检测硬件构成的基本部分包括&#xff1a;处理器、相机、镜头、光源。 其中&#xff0c;和光源相关的最重要的两个参数就是光源颜色和…

Linux shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件

Linux Debian12基于ImageMagick图像处理工具编写shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件&#xff0c;”多个图片分开生成多个PDF文件“或者“多个图片合并生成一个PDF文件” 在Linux系统中&#xff0c;使用ImageMagick可以图片格式转换&#xff0c…

批量提取zotero的论文构建知识库做问答的大模型(可选)——含转存PDF-分割统计PDF等

文章目录 提取zotero的PDF上传到AI平台保留文件名代码分成20个PDF视频讲解 提取zotero的PDF 右键查看目录 发现目录为 C:\Users\89735\Zotero\storage 写代码: 扫描路径‘C:\Users\89735\Zotero\storage’下面的所有PDF文件,全部复制一份汇总到"C:\Users\89735\Downl…

解决:websocket 1002 connection rejected 426upgrade required

这是问题是websocket客户端访问websocket服务端时候报的错&#xff0c;并非代码错误&#xff0c;需要配置一下k8s的路由策略 新增两行

Flutter组件————Container

Container Container 是 Flutter 中最常用的布局组件之一 参数 参数名称类型描述alignmentAlignmentGeometry定义子组件在其内部的对齐方式&#xff0c;默认为 null&#xff0c;即不改变子组件的位置。paddingEdgeInsetsGeometry内边距&#xff0c;用于在子组件周围添加空间…

ElasticSearch - 深入解析 Elasticsearch Composite Aggregation 的分页与去重机制

文章目录 Pre概述什么是 composite aggregation&#xff1f;基本结构after 参数的作用问题背景&#xff1a;传统分页的重复问题after 的设计理念响应示例 after 如何确保数据不重复核心机制Example步骤 1: 创建测试数据创建索引插入测试数据 步骤 2: 查询第一页结果查询第一页返…

MySQL 8.0:explain analyze 分析 SQL 执行过程

介绍 MySQL 8.0.16 引入一个实验特性&#xff1a;explain formattree &#xff0c;树状的输出执行过程&#xff0c;以及预估成本和预估返 回行数。在 MySQL 8.0.18 又引入了 EXPLAIN ANALYZE&#xff0c;在 formattree 基础上&#xff0c;使用时&#xff0c;会执行 SQL &#…

【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567

本文涉及知识点 打开打包代码的方法兼述单元测试 C动态规划 C图论 LeetCode3243. 新增道路查询后的最短距离 I 给你一个整数 n 和一个二维整数数组 queries。 有 n 个城市&#xff0c;编号从 0 到 n - 1。初始时&#xff0c;每个城市 i 都有一条单向道路通往城市 i 1&#…

120页PPT讲解ChatGPT如何与财务数字化转型的业财融合

此方案主要聚焦于利用ChatGPT技术与数字化转型推动业财融合&#xff0c;实现企业的价值最大化。首先&#xff0c;通过ChatGPT技术&#xff0c;企业可以构建生成式对话机器人&#xff0c;自动回答常见问题&#xff0c;减轻人工客服的压力&#xff0c;提高响应速度。这种机器人具…

旋转框目标检测自定义数据集训练测试流程

文章目录 前言一、数据集制作二、模型训练2.1 划分训练集验证集:2.2 配置yaml文件:2.3 训练 前言 旋转框目标检测&#xff08;Rotated bounding box object detection&#xff09;是计算机视觉领域的一项技术&#xff0c;它用于检测图像中具有任意方向的目标。与传统的水平矩形…

【QSS样式表 - ⑥】:QPushButton控件样式

文章目录 QPushBUtton控件样式QSS示例 QPushBUtton控件样式 常用子控件 常用伪状态 QSS示例 代码&#xff1a; QPushButton {background-color: #99B5D1;color: white;font-weigth: bold;border-radius: 20px; }QPushButton:hover {background-color: red; }QPushButton:p…

C# Random 随机数 全面解析

总目录 前言 一、Random 是什么&#xff1f; 1. 简介 表示伪随机数生成器&#xff0c;这是一种能够产生满足某些随机性统计要求的数字序列的算法。 public class Random继承&#xff1a;Object → Random 2. 构造函数 3. 属性 4. 方法 二、Random 的使用 1. Next() 或 Nex…

Linux网络——UDP的运用

Linux网络——UDP的运用 文章目录 Linux网络——UDP的运用一、引入二、服务端实现2.1 创建socket套接字2.2 绑定bind2.3 启动服务器2.4 IP的绑定的细节2.5 读取数据recvfrom 三、用户端实现3.1 绑定问题3.2 发送数据sendto 四、代码五、UDP实现网络聊天室&#xff08;简易版&am…

IDEA使用Alt + Enter快捷键自动接受返回值一直有final修饰的问题处理

在使用IDEA的过程中&#xff0c;使用快捷键Alt Enter在接收返回值时&#xff0c;可以快速完成参数接收&#xff0c;但前面一直会出现接收参数前面有final修饰的情况&#xff0c;效果如下所示&#xff1a; 看着真烦人呢&#xff0c;我们会发现在接受到返回值是上方有个 Declare…

【小白51单片机专用教程】protues仿真AT89C51入门

课程特点 无需开发板0基础教学软件硬件双修辅助入门 本课程面对纯小白&#xff0c;因此会对各个新出现的知识点在实例基础上进行详细讲解&#xff0c;有相关知识的可以直接跳过。课程涉及protues基本操作、原理图设计、数电模电、kell使用、C语言基本内容&#xff0c;所有涉及…