Maison >développement back-end >tutoriel php >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

小云云
小云云original
2018-01-16 13:40:142952parcourir

Cet article partage principalement 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. J'espère que cela aide tout le monde.

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 une chaîne personnalisée en PHP. est quelque peu 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 Il a une fonction auto-descriptive (connaître le type spécifique de l'objet à partir du résultat de la sérialisation.

Il ne suffit pas de connaître le type. 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 certaines performances -scénarios sensibles Dans ces circonstances, la sérialisation des objets ne peut pas être un obstacle, par exemple : des services hautes performances (j'utilise souvent protobuf pour sérialiser


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


Cet article explique uniquement la sérialisation et l'inverse dans PHP du point de vue du code PHP Le processus de sérialisation. 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. méthode de désérialisation unserialize

php fournit nativement une fonction de sérialisation d'objet, contrairement à c++...^_^ Il est également très simple à utiliser, juste 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(&#39;fobnn&#39;,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 à lire, vous. peut constater qu'il est mappé via le nom de l'objet/le nom du membre. Bien sûr, les noms d'étiquettes après sérialisation des membres avec des droits d'accès différents sont légèrement différents.


Selon les trois questions que j'ai mentionnées ci-dessus, nous pouvons alors passer à autre chose. jetez un œil

fobnn
O:5:"fobnn":2:{s:7:"hack_id";i:1;s:16:"fobnnhack_name";s:5:"fobnn";}
fobnn
1. Fonction auto-descriptive

O:5:"fobnn":2 où o représente le type d'objet et le nom du type est fobnn. 2 signifie qu'il y a 2 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. La fonction de

auto-description est principalement. pour enregistrer l'objet et Le nom du membre est implémenté.

2. Problèmes de performances

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

2. Méthode magique en désérialisation

Correspond au deuxième problème évoqué ci-dessus. En fait, il existe des solutions en PHP. L'une est par la méthode magique, et la. la deuxième consiste à utiliser la fonction de sérialisation personnalisée. Présentons-la d'abord les méthodes magiques __sleep et __wakeup



. __dormir d'abord avant la sérialisation et 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.
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();

Une fois la sérialisation terminée. Après cela, __wakeup sera utilisé ici, nous pouvons effectuer un travail de suivi, comme la reconnexion à la base de données. 3. Personnaliser l'interface sérialisable

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

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


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

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


4.PHP Type dynamique et désérialisation PHP
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();


Depuis la fonction auto-descriptive mentionnée ci-dessus, le type d'objet est enregistré dans le résultat de la sérialisation, et PHP est un langage typé dynamiquement , alors nous pouvons faire une expérience simple.
fobnn
C:5:"fobnn":23:{{"id":1,"name":"fobnn"}}
fobnn

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


On peut constater que l'objet a été sérialisé avec succès ! Et cela peut fonctionner normalement. Bien sûr, ce mécanisme de PHP fournit une syntaxe flexible et modifiable, mais il introduit également des risques de sécurité ! analyser PHP plus tard Problèmes de sécurité causés par les fonctionnalités de sérialisation et de désérialisation.

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();
Recommandations associées :


Partage d'exemples de code d'exemple de sérialisation de formulaire jQuery

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)

Explication sur la conversion des valeurs de formulaire sérialisé jQuery en exemples Json


Explication détaillée de la vulnérabilité de désérialisation de session de 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