php setcookieがcookie値をurlencodeする問題と解決
4437 ワード
1.質問
次のコードがあります.php
set()を呼び出してからget()を呼び出します.ページ出力
これは予想通りだ.しかしchromeのdebugツールを使用してクッキーを表示すると、personの値は
コンソールでdocumentを実行します.クッキー、結果は
すなわち,php側はクッキー値を設定して正常に取り出すことができるが,ブラウザやjs側から見ると,このクッキーは符号化されている.jsの使用が不便で、人工的に問題を調べるときにクッキーを見るのも不便です.
2.解決
マニュアルを調べると、setcookieは確かにcookie値にurlencodeを行ったことがわかります.どうやって迂回しますか?setcookieの本質はresponseヘッダにSet-Cookie応答ヘッダを加えることであると考え,ヘッダメソッドを直接用いることを試みた.set()コードは以下のように調整されます.
このとき,cookie中のperson値はchrome側から以下のように表示され,符号化は行われなかった.
3.リスク
2の方法はクッキー値が符号化される問題を解決したが,リスクをもたらすのではないか.答えはできる.たとえば、クッキーにセミコロン(httpプロトコルでは、Set-Cookieがキー値ペアを区切るキーワード)が付いている場合、バグが発生します.
問題を詳しく説明するために,まず2例のresponse header(主にSet-Cookie部分を切り取る)を見る.
コードを変更します
response headerが
ball後のセミコロンはperson値を中断し、後ろのsex:male;プロトコルは認識できないキー値ペアとして解析されるため無視される.
get()メソッドの出力やブラウザで見るperson値も
4.推奨事項
クッキーの値はできるだけ簡単で、特殊な記号を含まないので、setcookieがurlencodeを行っても何の変化もありません.特殊文字を含める必要がある場合は、プロトコル予約語を避けることに注意してください.
次のコードがあります.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を行っても何の変化もありません.特殊文字を含める必要がある場合は、プロトコル予約語を避けることに注意してください.