serialize()でMDB2のインスタンスを使い回したいとします。
serialize0.php
1
2
3
4
5
6
7
8
|
//MDB2
require_once('MDB2.php');
$db=MDB2::factory('mysqli://testuser:testpass@localhost');
//シリアライズ
$serial=serialize($db);
|
これだけでMDB2のインスタンスがさくっと一つの文字列になり、その後は保存して別の場所で開くなり、APIで他所に渡すなり自由に扱えます。
簡単ですが、この作り方、一つ重大なセキュリティ上の欠陥があります。
コンストラクタで引き渡したユーザ名やパスワードが平文で保存されてしまうのです。
パスワードは見せたくないけど、それ以外のインスタンスはそのまま渡したい、などということはできるでしょうか。
というわけでserialize()の動作を変更する方法があります。
しかも二種類。
http://jp.php.net/manual/ja/language.oop5.magic.php
http://jp.php.net/manual/ja/class.serializable.php
何故二種類もあるのかよくわかりませんが、
http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions
>@Eric: Because the Serializable interface is much more flexible. In this specific case, we don't use anything fancy, but for consistency, I always use the interface'
だそうです。
まあとりあえずマジックメソッドでやってみます。
SerialExample1.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
//適当なクラス
class SerialExample{
//インスタンス変数とか
private $string_serial='';
private $string_no_serial='';
//セッタゲッタ
public function __set($name,$value){
if($name=='string_serial' || $name=='string_no_serial'){
$this->{$name}=$value;
return true;
}else{
return false;
}
}
public function __get($name){
if($name=='string_serial' || $name=='string_no_serial'){
return $this->{$name};
}else{
return false;
}
}
//シリアライズ
public function __sleep(){
//シリアライズしたい変数名だけ返す
return array('string_serial');
}
//アンシリアライズ
public function __wakeup(){
/*
シリアライズ時に返した変数は自動的に元の場所に復帰する
それ以外の、特に行いたいこと(DBに接続しに行くとか)
がある場合はここに書く
*/
}
//↓クラスのおわり
}
|
serialize1.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//SerialExample
require_once('SerialExample1.php');
$example=new SerialExample();
//適当
$example->string_serial='aaaaa';
$example->string_no_serial='bbbbb';
//シリアライズ
$serial=serialize($example);
//アンシリアライズ
$desilial=unserialize($serial);
|
シリアライズ時に、変数名'string_serial'のみを返しています。
こうすることで指定した'string_serial'のみがシリアライズされ、シリアライズされた文字列は
string 'O:13:"SerialExample":1:{s:28:"�SerialExample�string_serial";s:5:"aaaaa";}'
となります。
シリアライズ前のSerialExampleクラスの中身にはstring_serial及びstring_no_serialが両方とも入っています。
object(SerialExample)[1] public 'string_serial' => string 'aaaaa' (length=5) public 'string_no_serial' => string 'bbbbb' (length=5)
一旦シリアライズ後アンシリアライズしたときには、string_serialだけが元に戻ります。
object(SerialExample)[2] public 'string_serial' => string 'aaaaa' (length=5) public 'string_no_serial' => string '' (length=0)
パスワードのような、平文で送信されると困る部分だけシリアライズ対象から排除することができるようになりました。
めでたし。
全然どうでもいいんですがPHP以外ではデシリアライズです。
何故PHPだけアンシリアライズなんだろう。
PR
トラックバック
トラックバックURL: