Dieser Artikel teilt Ihnen das relevante Wissen über PHP-Serialisierungs- und Deserialisierungsprinzipien in der PHP-Deserialisierungs-Schwachstellenreihe mit. Freunde, die dies benötigen, können darauf zurückgreifen.
0. Vorwort
Die Serialisierung von Objekten wird nicht im Detail beschrieben ähnlich wie json.
Wir müssen mehrere Probleme lösen, wenn wir die Serialisierung und Deserialisierung von Objekten in einer beliebigen Sprache entwerfen.
Nach der Serialisierung eines Objekts ist das Serialisierungsergebnis eine selbstbeschreibende Funktion (Kenntnis der spezifischen Typ dieses Objekts aus dem Serialisierungsergebnis
Die Kenntnis des Typs reicht nicht aus, Sie müssen natürlich auch den spezifischen Wert kennen, der diesem Typ entspricht).
Berechtigungskontrolle während der Serialisierung, Sie können Serialisierungsfelder usw. anpassen. Dies ist beispielsweise sehr praktisch in Golang.
Zeitleistungsprobleme: In einigen leistungsempfindlichen Szenarien ist die Objektserialisierung nicht möglich ein Hindernis sein, zum Beispiel: Hochleistungsdienste (ich verwende oft Protobuf für die Serialisierung). Probleme mit der Speicherplatzleistung: Das Ergebnis nach der Serialisierung darf nicht zu lang sein, z. B. ein int im Speicherobjekt. Nach der Serialisierung beträgt die Datenlänge das Zehnfache der Länge von int. Dann liegt ein Problem mit diesem Serialisierungsalgorithmus vor.
Dieser Artikel erläutert nur die Serialisierung und Deserialisierung in PHP aus der Perspektive des PHP-Codeprozesses . Denken Sie daran, dass Serialisierung und Deserialisierung nur für Objektdaten gelten.
1 >
PHP bietet im Gegensatz zu C++ nativ eine Objektserialisierungsfunktion...^_^ Es ist auch sehr einfach zu verwenden, nur zwei Schnittstellen.class fobnn { public $hack_id; private $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { echo $this->hack_name.PHP_EOL; } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); //通过serialize接口序列化 echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr);//通过unserialize反序列化 $toobj->print();
fobnn O:5:"fobnn":2:{s:7:"hack_id";i:1;s:16:"fobnnhack_name";s:5:"fobnn";} fobnn
Diese Zeichenfolge ist das Ergebnis der Serialisierung. Nach dem Lesen können Sie feststellen, dass sie über den Objektnamen abgebildet wird /Mitgliedsname. Natürlich sind die Labelnamen nach der Serialisierung von Mitgliedern mit unterschiedlichen Zugriffsrechten etwas anders.
Gemäß den drei oben genannten Fragen können wir einen Blick auf
<🎜 werfen >1. Selbstbeschreibende Funktion O:5:"fobnn":2 wobei o den Objekttyp darstellt und der Typname fobnn ist. In diesem Format zeigt die 2 an, dass es zwei Mitglieder gibt Bei den Mitgliedsobjekten handelt es sich tatsächlich um den gleichen Satz von Unterbeschreibungen. Die Funktion der Selbstbeschreibung besteht hauptsächlich darin, das Objekt durch Zeichenfolgen aufzuzeichnen und die Namen der Mitglieder.2. LeistungsproblemeDie Zeitleistung der PHP-Serialisierung wird in diesem Artikel nicht analysiert, aber die Serialisierungsergebnisse sind denen tatsächlich ähnlich definiert durch json/bson Ein Protokoll hat einen Protokollheader, der den Typ beschreibt, und der Protokollhauptteil beschreibt den Wert, der dem Typ entspricht. Das Serialisierungsergebnis wird nicht komprimiert. Magie in der Deserialisierung Die Methode entspricht dem zweiten oben genannten Problem. Tatsächlich gibt es auch Lösungen in PHP. Eine davon ist eine magische Methode und die zweite ist eine benutzerdefinierte Serialisierungsfunktion. Lassen Sie es uns zuerst vorstellen. Die magischen Methoden __sleep und __wakeupclass fobnn { public $hack_id; private $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { echo $this->hack_name.PHP_EOL; } public function __sleep() { return array("hack_name"); } public function __wakeup() { $this->hack_name = 'haha'; } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print();
fobnn O:5:"fobnn":1:{s:16:"fobnnhack_name";s:5:"fobnn";} haha
rufen __sleep vor der Serialisierung auf und kehren zurück ist ein Array von Mitgliedsnamen, die serialisiert werden müssen. In dem Fall, dass ich nur hack_name zurückgegeben habe, ist im Ergebnis nur das Mitglied hack_name serialisiert.
in Nach Abschluss der Serialisierung können wir einige Folgearbeiten durchführen, z. B. die erneute Verbindung zur Datenbank.
3interface Serializable { abstract public string serialize ( void ) abstract public void unserialize ( string $serialized ) }
Über diese Schnittstelle können wir das Serialisierungs- und Deserialisierungsverhalten anpassen. Diese Funktion kann hauptsächlich zur Anpassung unseres Serialisierungsformats verwendet werden.
class fobnn implements Serializable
{
public $hack_id;
private $hack_name;
public function __construct($name,$id)
{
$this->hack_name = $name;
$this->hack_id = $id;
}
public function print()
{
echo $this->hack_name.PHP_EOL;
}
public function __sleep()
{
return array('hack_name');
}
public function __wakeup()
{
$this->hack_name = 'haha';
}
public function serialize()
{
return json_encode(array('id' => $this->hack_id ,'name'=>$this->hack_name ));
}
public function unserialize($var)
{
$array = json_decode($var,true);
$this->hack_name = $array['name'];
$this->hack_id = $array['id'];
}
}
$obj = new fobnn('fobnn',1);
$obj->print();
$serializedstr = serialize($obj);
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);
$toobj->print();
fobnn C:5:"fobnn":23:{{"id":1,"name":"fobnn"}} fobnn
Wenn eine benutzerdefinierte Serialisierungsschnittstelle verwendet wird, ist unsere magische Methode nutzlos.
4.Dynamischer PHP-Typ und PHP-DeserialisierungDa die oben erwähnte selbstbeschreibende Funktion den Objekttyp im Serialisierungsergebnis speichert und PHP eine dynamische Typsprache ist, dann wir kann ein einfaches Experiment durchführen.
class fobnn { public $hack_id; public $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { var_dump($this->hack_name); } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print(); $toobj2 = unserialize("O:5:\"fobnn\":2:{s:7:\"hack_id\";i:1;s:9:\"hack_name\";i:12345;}"); $toobj2->print();
Wir ändern das Deserialisierungsergebnis von hack_name in den Typ int, i:12345
string(5) "fobnn" O:5:"fobnn":2:{s:7:"hack_id";i:1;s:9:"hack_name";s:5:"fobnn";} string(5) "fobnn" int(12345)
Es kann festgestellt werden, dass das Objekt wieder erfolgreich serialisiert wurde! Natürlich bietet dieser Mechanismus von PHP eine flexible und veränderbare Syntax, birgt jedoch auch Sicherheitsrisiken um die Sicherheitsprobleme zu analysieren, die durch die Serialisierungs- und Deserialisierungsfunktionen von PHP verursacht werden.
Das oben Genannte ist das gesamte Wissen, das wir über die Prinzipien der PHP-Serialisierung und -Deserialisierung zusammengestellt haben.
Artikel, die Sie interessieren könnten:
Erläuterung des Code-Implementierungsprozesses für die WeChat-QR-Code-Anmeldefunktion basierend auf Swoole
Detaillierte Erläuterung der Implementierungsmethode von Hello Word in der PHP7-Erweiterungsentwicklung
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der PHP-Serialisierungs- und Deserialisierungsprinzipien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!