$_COOKIE是php中一個非常好用的東西,但是有時我們會碰到同域名下的不同子域名一樣,這樣就會存在只能保留一個cookie的問題,下面小編來給各位同學介紹一下。
PHP的超全局變量$_COOKIE帶來了很多便利,在某些情況下也會造成困惑。比如在根域和子域下存在同名cookie,$_COOKIE中只能保存一個,應該是哪個?
RFC建議使用長度最長的那個,這樣精度最高,但是不同浏覽器處理方式不同。我只測試了Chrome,Chrome中根域和子域的同名cookie都發送出去了,這樣PHP只接收排在前面的同名cookie,後面的被忽略,這樣很容易接收到錯誤的值。據說Safari遵循了RFC的建議,沒有親自測試,其他浏覽器也沒有測試。
首先通過SwitchHosts設定虛擬域名:www.bKjia.c0m,並且配置好Web服務器,當然,你手動設置Hosts文件也可以,我本意是為了多介紹幾個工具。
然後編寫設置Cookie的PHP腳本,先設置子域,再設置根域:
代碼如下 復制代碼<?php
setcookie("bar", "www", time() + 10, "/", "www.bKjia.c0m");
setcookie("bar", "foo", time() + 10, "/", ".bKjia.c0m");
?>
再編寫浏覽Cookie的腳本:
代碼如下 復制代碼<?php
var_dump($_COOKIE);
?>
BTW:最初寫腳本的時候我竟然在setcookie前使用了var_dump,也就是在發送請求頭之前有了輸出,犯了這樣的初學者錯誤實在是罪過,可更令人驚訝的是腳本沒有報錯,查了半天原來是因為php.ini裡缺省output_buffering = 4096。
先設置再浏覽,就能看到結果了,結果顯示有效的是子域下的Cookie。
重開一個浏覽器窗口,並使用WebDeveloper刪除Cookie,或手動刪除,避免對結果造成影響。
然後調換兩次調用setcookie的順序,也就是先設置根域,再設置子域:
代碼如下 復制代碼<?php
setcookie("bar", "foo", time() + 10, "/", ".bKjia.c0m");
setcookie("bar", "www", time() + 10, "/", "www.bKjia.c0m");
?>
先設置再浏覽,就能看到結果了,結果顯示有效的是根域下的Cookie。
重復兩次測試過程,並用Firebug記錄下請求頭的差異:
第一次先設置子域,再設置根域:請求頭Cookie的值是bar=www;bar=foo,結果有效的是bar=www
第二次先設置根域,再設置子域:請求頭Cookie的值是bar=foo;bar=www,結果有效的是bar=foo
也就說,同名Cookie對於服務端PHP來說,在請求頭Cookie中,哪個在前哪個生效,後面的會被忽略。
如果使用的不是Firefox,那就用不了Firebug,此時可以用PHP代碼來檢測Cookie頭:
代碼如下 復制代碼if (isset($_SERVER['HTTP_COOKIE'])) var_dump($_SERVER['HTTP_COOKIE']);
以上的實驗結論是基於Firefox而言的,由於不同的浏覽器發送Cookie的策略可能有差異,所以在其他浏覽器上結果可能會有所不同,比如在Safari下就始終是子域有效,其他浏覽器如Opera,Chrome等未仔細測試。鑒於這個混亂的結論,所以還是不要在子域和根域下使用同名Cookie為好!
結論:目前在根域和子域中使用同名COOKIE是非常不明智的