Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der PHP-Serialisierungs- und Deserialisierungsprinzipien

Detaillierte Erläuterung der PHP-Serialisierungs- und Deserialisierungsprinzipien

小云云
小云云Original
2018-01-16 13:40:142912Durchsuche

Dieser Artikel teilt Ihnen hauptsächlich das relevante Wissen über die PHP-Serialisierungs- und Deserialisierungsprinzipien in der PHP-Deserialisierungs-Schwachstellenreihe mit. Freunde, die dies benötigen, können darauf zurückgreifen. Ich hoffe, es hilft allen.

Vorwort

Die Serialisierung und Deserialisierung von Objekten wird nicht im Detail beschrieben. Das Ergebnis der Serialisierung in PHP ist ein von PHP angepasstes Format ist json etwas ähnlich.

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 Es hat eine selbstbeschreibende Funktion (Den spezifischen Typ des Objekts aus dem Serialisierungsergebnis kennen.

Es reicht nicht aus, den Typ zu kennen. Natürlich müssen Sie 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 Fällen -Sensible Szenarien Unter diesen Umständen kann die Objektserialisierung kein Hindernis sein, zum Beispiel: Hochleistungsdienste (ich verwende häufig Protobuf zum Serialisieren


Probleme mit der Speicherplatzleistung: Das Ergebnis nach der Serialisierung kann nicht auch sein). B. bei einem Int-Objekt, nach der Serialisierung die Datenlänge das Zehnfache der Länge von int beträgt, liegt ein Problem mit diesem Serialisierungsalgorithmus vor.


In diesem Artikel werden nur die Serialisierung und die Umkehrung erläutert PHP aus der Perspektive des PHP-Codes. Denken Sie daran, dass Serialisierung und Deserialisierung nur für Objektdaten gelten.

1 Deserialisierungsmethode unserialize

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
Siehe die zweite Zeile der Ausgabe. Diese Struktur ist eigentlich sehr leicht zu verstehen Sie können feststellen, dass die Zuordnung über den Objektnamen/Mitgliedsnamen erfolgt. Natürlich unterscheiden sich die Etikettennamen nach der Serialisierung von Mitgliedern mit unterschiedlichen Zugriffsrechten geringfügig.

Gemäß den drei Fragen, die ich oben erwähnt habe, können wir es tun Werfen Sie einen Blick darauf

1. Selbstbeschreibende Funktion

O:5:"fobnn":2 wobei o den Objekttyp darstellt und der Typname fobnn ist 2 bedeutet, dass es zwei Mitgliedsobjekte gibt. Es handelt sich tatsächlich um die gleichen Unterbeschreibungen.

Die selbstbeschreibende Funktion zeichnet die auf Objekte und Der Name des Mitglieds ist implementiert.

2. Leistungsprobleme

Die Zeitleistung der PHP-Serialisierung wird in diesem Artikel nicht analysiert, die Serialisierungsergebnisse jedoch Eigentlich ähnlich dem durch json/bson definierten Protokoll, es gibt einen Protokollheader, der Protokollheader beschreibt den Typ und der Protokollhauptteil beschreibt den dem Typ entsprechenden Wert, und das Serialisierungsergebnis wird nicht komprimiert

2. Magische Methode bei der Deserialisierung

Entspricht dem zweiten oben genannten Problem. Tatsächlich gibt es eine Lösung durch eine magische Methode Benutzerdefinierte Serialisierungsfunktion. Lassen Sie uns zuerst die magischen Methoden __sleep und __wakeup vorstellen Serialisierung und Rückgabe eines Arrays von Mitgliedsnamen, die serialisiert werden müssen. In dem Fall, dass ich nur hack_name zurückgegeben habe, ist dies der Fall Ergebnis.

Nachdem die Serialisierung abgeschlossen ist, können wir einige Folgearbeiten durchführen, z. B. die erneute Verbindung zur Datenbank die Serialisierbare Schnittstelle


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;
 }
 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();

Über diese Schnittstelle können wir das Serialisierungs- und Deserialisierungsverhalten anpassen. Diese Funktion kann hauptsächlich zur Anpassung unseres Serialisierungsformats verwendet werden.

fobnn
O:5:"fobnn":1:{s:16:"fobnnhack_name";s:5:"fobnn";}
haha

Nach der Verwendung der benutzerdefinierten Serialisierungsschnittstelle ist unsere magische Methode nutzlos.


4. Dynamischer PHP-Typ und PHP-Deserialisierung

interface Serializable {
abstract public string serialize ( void )
abstract public void unserialize ( string $serialized )
}

Da die oben erwähnte selbstbeschreibende Funktion den Objekttyp im Serialisierungsergebnis speichert und PHP eine dynamisch typisierte Sprache ist, dann wir Sie können ein einfaches Experiment durchführen.


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();


Wir ändern das Deserialisierungsergebnis von hack_name in den Typ int, i:12345

fobnn
C:5:"fobnn":23:{{"id":1,"name":"fobnn"}}
fobnn

Es kann festgestellt werden, dass das Objekt erfolgreich wieder serialisiert wurde. Natürlich bietet dieser PHP-Mechanismus eine flexible und veränderbare Syntax, birgt jedoch auch Sicherheitsrisiken Sicherheitsprobleme, die durch Serialisierungs- und Deserialisierungsfunktionen verursacht werden.
Verwandte Empfehlungen:

Beispiel für jQuery-Formularserialisierung, Code-Beispielfreigabe

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();

Erklärung zum Konvertieren von jQuery-serialisierten Formularwerten in Json-Beispiele


Ausführliche Erklärung der PHP-Sicherheitslücke bei der Sitzungsdeserialisierung
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)

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn