Maison  >  Article  >  développement back-end  >  Explication détaillée des principes de sérialisation et de désérialisation PHP

Explication détaillée des principes de sérialisation et de désérialisation PHP

jacklove
jackloveoriginal
2018-06-30 18:01:061773parcourir

Cet article partage avec vous les connaissances pertinentes sur les principes de sérialisation et de désérialisation PHP dans la série sur les vulnérabilités de désérialisation PHP. Les amis qui en ont besoin peuvent s'y référer.

0. Préface

La sérialisation et la désérialisation des objets ne seront pas décrites en détail. Le résultat de la sérialisation en PHP est un format de chaîne personnalisé en PHP. similaire à json.

Nous devons résoudre plusieurs problèmes lors de la conception de la sérialisation et de la désérialisation d'objets dans n'importe quel langage

Après la sérialisation d'un objet, le résultat de la sérialisation est une fonction auto-descriptive (connaissant le spécifique type de cet objet à partir du résultat de la sérialisation,

connaître le type ne suffit pas, bien sûr il faut aussi connaître la valeur spécifique correspondant à ce type).

Contrôle des autorisations pendant la sérialisation, vous pouvez personnaliser les champs de sérialisation, etc., par exemple, il est très pratique de le faire dans Golang.

Problèmes de performances temporelles : dans certains scénarios sensibles aux performances, la sérialisation des objets ne peut pas être un frein, par exemple : des services hautes performances (j'utilise souvent protobuf pour la sérialisation

Problèmes de performances spatiales : le résultat après sérialisation ne peut pas être trop long, comme un objet int en mémoire). après la sérialisation, la longueur des données devient 10 fois supérieure à la longueur de int, il y a alors un problème avec cet algorithme de sérialisation

Cet article explique uniquement la sérialisation et la désérialisation en PHP du point de vue du processus de code PHP. .N'oubliez pas que la sérialisation et la désérialisation ne fonctionnent que sur les données d'objet. Toute personne ayant de l'expérience dans le développement orienté objet devrait facilement comprendre cela

1. 🎜>php fournit nativement une fonction de sérialisation d'objets, contrairement à c++...^_^ Il est également très simple à utiliser, seulement deux interfaces.

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

Voir la deuxième ligne de sortie, cette chaîne est le résultat de la sérialisation, cette structure est en fait très facile à comprendre. mappés par nom d'objet/nom de membre Bien sûr, les noms de balises après la sérialisation des membres avec des droits d'accès différents sont légèrement différents
fobnn
O:5:"fobnn":2:{s:7:"hack_id";i:1;s:16:"fobnnhack_name";s:5:"fobnn";}
fobnn

Selon les trois choses que j'ai mentionnées ci-dessus, nous pouvons alors jeter un œil à <.>

1. Fonction auto-descriptive

O:5 : "fobnn":2 où o représente le type d'objet, et le nom du type est fobnn, en utilisant ceci Dans ce format, le 2 à la end indique qu'il y a deux objets membres.

Concernant les objets membres, il s'agit en fait du même ensemble de sous-descriptions. Il s'agit d'une définition récursive de

. principalement via String enregistre les noms des objets et des membres pour y parvenir.

2. Problèmes de performances

Les performances temporelles de la sérialisation PHP ne seront pas analysées dans cet article, mais voir les détails plus tard. le résultat de la sérialisation est en fait similaire à json Le protocole défini par /bson a un en-tête de protocole décrit le type et le corps du protocole décrit la valeur correspondant au type. Le résultat de la sérialisation ne sera pas compressé. 🎜>

2. Désérialisation La méthode magique

correspond au deuxième problème évoqué plus haut. En fait, il existe aussi des solutions en PHP. On passe par la méthode magique, et la. la deuxième est une fonction de sérialisation personnalisée. Commençons par présenter les méthodes magiques __sleep et __wakeup


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 = &#39;haha&#39;;
 }
}
$obj = new fobnn(&#39;fobnn&#39;,1);
$obj->print();
$serializedstr = serialize($obj);
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);
$toobj->print();
.

dans la séquence Avant la sérialisation, __sleep sera d'abord appelé pour renvoyer un tableau de noms de membres qui doivent être sérialisés. De cette façon, nous pouvons contrôler les données qui doivent être sérialisées. Dans le cas où je n'ai renvoyé que hack_name. . Vous pouvez voir que seul le membre hack_name est sérialisé dans le résultat.

Une fois la sérialisation terminée, __wakeup sera utilisé ici, nous pouvons effectuer un travail de suivi, comme la reconnexion à la base de données.

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

3. Personnaliser l'interface sérialisable

Grâce à cette interface, nous pouvons personnaliser le comportement de la sérialisation et désérialisation. Cette fonction peut principalement être utilisée pour personnaliser notre format de séquence.

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

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(&#39;hack_name&#39;);
 }

 public function __wakeup()
 {
  $this->hack_name = &#39;haha&#39;;
 }

 public function serialize()
 {
  return json_encode(array(&#39;id&#39; => $this->hack_id ,&#39;name&#39;=>$this->hack_name ));
 }

 public function unserialize($var)
 {
  $array = json_decode($var,true);
  $this->hack_name = $array[&#39;name&#39;];
  $this->hack_id = $array[&#39;id&#39;];
 }
}
$obj = new fobnn(&#39;fobnn&#39;,1);
$obj->print();
$serializedstr = serialize($obj);
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);
$toobj->print();

Après avoir utilisé l'interface de sérialisation personnalisée, nous La méthode magique est inutile.

4. Type dynamique PHP et désérialisation PHP
fobnn
C:5:"fobnn":23:{{"id":1,"name":"fobnn"}}
fobnn

Depuis la fonction auto-descriptive mentionnée ci-dessus, alors le type d'objet est enregistré dans le résultat de la sérialisation, et php est un langage typé dynamiquement, nous pouvons donc faire une expérience simple.


Nous modifions le résultat de la désérialisation de hack_name en type int, i:12345

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(&#39;fobnn&#39;,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();

Vous pouvez constater que l'objet est sérialisé avec succès et cela peut ! fonctionne normalement ! . Bien sûr, ce mécanisme de PHP fournit une syntaxe flexible, mais il introduit également des risques de sécurité. Nous continuerons à analyser les problèmes de sécurité causés par les fonctionnalités de sérialisation et de désérialisation de PHP

Ce qui précède. nous avons compilé toutes les connaissances sur les principes de sérialisation et de désérialisation PHP, merci pour votre soutien au site Web chinois php.

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)

Articles qui pourraient vous intéresser :

Explication du processus d'implémentation du code pour la fonction de connexion par analyse de code WeChat basée sur Swoole

Explication détaillée de la méthode d'implémentation de hello word dans le développement de l'extension PHP7


Explication détaillée de la méthode basée sur les fonctions d'utilisation de la bibliothèque lib dans Développement d'extensions PHP



Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn