php setcookieがcookie値をurlencodeする問題と解決

4437 ワード

1.質問
次のコードがあります.php
class Cookie{
    protected $_key = "person";
    protected $_val = "name:ball,sex:male";

    public function set(){
        $duration = 0;
        $path = "/";
        setcookie($this->_key, $this->_val, $duration, $path);
    }   

    public function get(){
        echo $_COOKIE[$this->_key];
    }   
}

set()を呼び出してからget()を呼び出します.ページ出力
name:ball,sex:male

これは予想通りだ.しかしchromeのdebugツールを使用してクッキーを表示すると、personの値は
name%3Aball%2Csex%3Amale

コンソールでdocumentを実行します.クッキー、結果は
"person=name%3Aball%2Csex%3Amale"

すなわち,php側はクッキー値を設定して正常に取り出すことができるが,ブラウザやjs側から見ると,このクッキーは符号化されている.jsの使用が不便で、人工的に問題を調べるときにクッキーを見るのも不便です.
2.解決
マニュアルを調べると、setcookieは確かにcookie値にurlencodeを行ったことがわかります.どうやって迂回しますか?setcookieの本質はresponseヘッダにSet-Cookie応答ヘッダを加えることであると考え,ヘッダメソッドを直接用いることを試みた.set()コードは以下のように調整されます.
public function set(){
    $str = sprintf("Set-Cookie:%s=%s;path=/", $this->_key, $this->_val);
    header($str);
}  

このとき,cookie中のperson値はchrome側から以下のように表示され,符号化は行われなかった.
name:ball,sex:male

3.リスク
2の方法はクッキー値が符号化される問題を解決したが,リスクをもたらすのではないか.答えはできる.たとえば、クッキーにセミコロン(httpプロトコルでは、Set-Cookieがキー値ペアを区切るキーワード)が付いている場合、バグが発生します.
問題を詳しく説明するために,まず2例のresponse header(主にSet-Cookie部分を切り取る)を見る.
Server: nginx/1.4.1
Set-Cookie: person=name:ball,sex:male;path=/
Transfer-Encoding: chunked

コードを変更します
 
protected $_val = "name:ball,sex:male";
  
protected $_val = "name:ball;sex:male";

response headerが
Server: nginx/1.4.1
Set-Cookie: person=name:ball;sex:male;path=/
Transfer-Encoding: chunked

ball後のセミコロンはperson値を中断し、後ろのsex:male;プロトコルは認識できないキー値ペアとして解析されるため無視される.
get()メソッドの出力やブラウザで見るperson値も
name:ball

4.推奨事項
クッキーの値はできるだけ簡単で、特殊な記号を含まないので、setcookieがurlencodeを行っても何の変化もありません.特殊文字を含める必要がある場合は、プロトコル予約語を避けることに注意してください.