>백엔드 개발 >PHP 튜토리얼 >PHP 직렬화 및 역직렬화 원칙에 대한 자세한 설명

PHP 직렬화 및 역직렬화 원칙에 대한 자세한 설명

小云云
小云云원래의
2018-01-16 13:40:142954검색

이 문서는 주로 PHP 역직렬화 취약점 시리즈에서 PHP 직렬화 및 역직렬화 원칙에 대한 관련 지식을 공유합니다. 이 문서가 필요한 친구는 이를 참조할 수 있습니다. 그것이 모두에게 도움이 되기를 바랍니다.

머리말

객체의 직렬화 및 역직렬화는 자세히 설명하지 않습니다. PHP에서 직렬화의 결과는 json과 다소 유사한 PHP 사용자 정의 문자열 형식입니다.

우리는 모든 언어로 디자인합니다. 객체의 역직렬화는 여러 가지 문제를 해결해야 합니다

객체를 직렬화한 후 직렬화 결과에는 자체 설명 기능이 있습니다(객체의 특정 유형은 직렬화 결과에서 알 수 있습니다.

물론 유형을 아는 것만으로는 충분하지 않습니다) 또한 이 유형에 해당하는 특정 값을 알아야 합니다.

직렬화 중 권한 제어, 직렬화 필드 등을 사용자 정의할 수 있습니다. 예를 들어 golang에서 수행하는 것이 매우 편리합니다. : 성능에 민감한 일부 시나리오에서는 고성능 서비스(직렬화를 위해 protobuf를 자주 사용함)와 같이 객체 직렬화가 방해가 될 수 없습니다.

공간 성능 문제: 직렬화 후 결과가 너무 길면 안 됩니다. 메모리의 int 객체가 직렬화되고 데이터 길이가 int 길이의 10배가 되면 직렬화 알고리즘에 문제가 있는 것입니다.

이 문서에서는 PHP 코드의 관점에서 직렬화 및 역직렬화만 설명합니다. . 직렬화 및 역직렬화는 객체 데이터에서만 작동한다는 점을 기억하세요. 객체 지향 개발 경험이 있는 사람이라면 누구나 쉽게 이해할 수 있습니다.

1. 직렬화 및 역직렬화 메서드 unserialize

php는 C++와 달리 객체 직렬화 기능을 기본적으로 제공합니다. .^_^. 인터페이스가 2개뿐이므로 사용하기도 매우 간단합니다.

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

출력의 두 번째 줄을 참조하세요. 문자열은 직렬화의 결과입니다. 이 구조는 실제로 이해하기 쉽습니다. .. 객체명/멤버명을 통해 매핑되는 것을 알 수 있습니다. 물론, 접근권한이 다른 멤버들을 직렬화한 후의 라벨명은 약간 다릅니다.

위에서 언급한 3가지 질문에 따르면, a look

1. 자체 설명 기능

O:5:"fobnn":2 여기서 o는 객체 유형을 나타내고 유형 이름은 fobnn입니다. 이 형식을 사용하면 다음 2는 멤버 객체가 두 개 있음을 나타냅니다.

멤버 개체에 대해서는 실제로 동일한 하위 설명 집합입니다.

자기 설명 기능은 주로 개체 및 멤버 이름을 문자열로 기록하여 구현됩니다. 문제

이 기사에서는 PHP 직렬화의 시간 성능을 분석하지 않지만, 직렬화 결과는 실제로 json/bson에서 정의한 프로토콜과 유사하며, 프로토콜 헤더는 유형을 설명합니다. , 프로토콜 본문에서는 해당 유형에 해당하는 값이 직렬화 결과를 압축하지 않는다고 설명합니다.

2. 역직렬화의 매직 메서드

실제로는 위에서 언급한 두 번째 문제에 해당합니다. 하나는 매직 메소드를 통하는 것이고, 두 번째는 커스텀 직렬화 함수입니다. 먼저 매직 메소드인 __sleep과 __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 = '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

을 소개하겠습니다. __sleep이 먼저 호출되어 이를 반환합니다. 는 직렬화해야 하는 멤버 이름의 배열입니다. 이를 통해 직렬화해야 하는 데이터를 제어할 수 있습니다. 이 경우에는 hack_name 멤버만 반환된 것을 볼 수 있습니다

직렬화가 완료되면 데이터베이스에 다시 연결하는 등의 후속 작업을 수행할 수 있는 __wakeup으로 이동합니다.

3 직렬화 가능 인터페이스 사용자 정의

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('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

사용자 정의 직렬화 인터페이스를 사용하면 마법 메서드가 쓸모가 없습니다.


4 .PHP 동적 유형 및 PHP deserialization

위에서 언급한 자체 설명 함수이므로 직렬화 결과에 객체의 유형이 저장되며 PHP는 동적 유형 언어이므로 간단한 실험을 할 수 있습니다.

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

수정했습니다 hack_name을 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)

객체가 성공적으로 직렬화되었음을 확인할 수 있습니다. 물론, 이러한 종류의 PHP 메커니즘은 유연한 구문을 제공합니다. 그러나 보안 위험도 발생합니다.

관련 권장 사항:

jQuery 양식 직렬화 예제 코드 예제 공유


JQuery 직렬화 양식 값이 Json으로 변환됩니다. 설명 예시

PHP 세션 역직렬화 취약점에 대한 자세한 설명

위 내용은 PHP 직렬화 및 역직렬화 원칙에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.