cookie系列(二)header302跳轉引發的思考
今天我們來看以下兩個現象,並解釋這兩個現象的原因:
第一個現象:
php檔案執行過程中如果碰到有header("Location:某個頁面URL");這種語句,會直接跳轉到另一個頁面,但是這裡的跳轉並不會影響當前php檔案的繼續執行。
下面我們用程式碼跑一下看看上面的現象是否是成立的:
(1)http://a.com/test.php程式碼如下:
(2)http://b.com/test.php程式碼如下:
(3)訪問http://a.com/test.php顯示以下結果:
此時,我們發現我們顯示的結果頁中,位址列變成了b.com/test.php,同時,頁面輸出了123,然後我們也看到a.com下面cookie被寫入成功了,而且a.txt檔案也生成了。
實驗證明,header302跳轉之後,其下面的程式碼還是會繼續執行,那麼原因是什麼呢?
很多人不明白,不是已經跳轉走了嗎?跳走了怎麼可能還執行?
要解釋這個現象其實原理很簡單,客戶端a向服務端b傳送請求,服務端b處理完成之後,響應回客戶端a。注意這裡面的用詞,處理完成!處理完成!處理完成!是服務端b處理完成之後才會響應客戶端。
上程式碼,我們證實一下是不是處理完成之後響應回客戶端:
(1)http://a.com/test.php程式碼如下:
(2)http://b.com/test.php程式碼不變如下:
(3)訪問http://a.com/test.php顯示以下結果:
瀏覽器一直在載入,10秒之後才跳轉到http://b.com/test.php頁面。
上圖中程式碼寫的很清楚,先header跳轉然後在sleep(10),頁面沒有立即跳轉而是停了10秒鐘再發生跳轉。
所以要想header之後程式碼不繼續執行,我們只需要在header後面exit就可以了,程式碼如下:
那麼後面的程式碼就不會被執行!
到這個地方,我們第一個現象的原因其實已經解釋完了,現在我們來看一個細節,http://a.com/test.php程式碼如下圖一所示,訪問http://a.com/test.php響應回來的內容為空,見下圖二,我們雖然有echo 有print_r還有var_dump,但是都沒有被輸出。
(圖一)
(圖二)
通過谷歌瀏覽器,我們看到服務端雖然沒有返回內容,但是返回了響應訊息頭,如下:
由此看來,當伺服器端在設定header響應報文給客戶端的時候,如果狀態碼是302,那麼伺服器端就不會返回具體的資料內容給客戶端,而瀏覽器看到302,也不用去關心返回的響應內容,直接拿著響應報文裡面的location地址前往下一站去嘍,這樣的方式也防止了不必要的資料傳輸。
這讓我想到了另一張情況,客戶端去情況求服務端的時候,服務端驗證請求資源沒有發生改變會返回304狀態碼,那麼這個時候伺服器端也不會返回響應內容,通過304狀態碼去告訴瀏覽器,這個資源沒有更改過,你直接從自己的快取中去拿吧。
我們繼續第二個現象:
header 302跳轉可以跳轉到其他網站設定cookie而curl無法給其他站點設定cookie,這又是為什麼?
在之前,我們其實探討過這個問題jsonp系列(三)兩種寫法請求後端設定cookie,為啥一個可以,一個不可以?,其中我們講到了,為什麼curl不能跨站設定cookie,但是今天有小夥伴問,為啥,header 跳轉能夠給其他站點設定cookie呢?
還是先看程式碼吧:
(1)http://a.com/test.php程式碼如下:
(2)http://b.com/test.php程式碼如下:
(3)訪問http://a.com/test.php我們發現頁面跳轉到http://b.com/test.php並且b.com下被設定了cookie。
這又是什麼原因呢?
為啥curl不可以,header302卻可以?
通過谷歌瀏覽器我們可以發現:
如圖中所示,當我們在位址列敲下http://a.com/test.php並且敲下回車的時候,通過谷歌瀏覽器我們發現了兩個請求都是test.php,分別如下:
如上圖,當瀏覽器去請求http://a.com/test.php的時候,a.com服務端返回302給瀏覽器,瀏覽器拿到響應訊息頭的location,存到記憶體中,此時瀏覽器與http://a.com的通訊過程其實就結束了,也就是一個請求與響應就結束了,然後瀏覽器拿著location地址重新請求http://b.com/test.php,於是我們看到瀏覽器跳轉的畫面,此時b。com返回給瀏覽器的響應訊息頭裡面有set-cookie的資訊,那麼瀏覽器得到這個cookie資訊生成檔案並存放到了瀏覽器預設cookie存放的目錄下。
如圖所示:
header跳轉的情況:
在第6個步驟中,b.com返回了cookie資訊給瀏覽器,瀏覽器存下了b.com的cookie資訊。
curl請求的情況:
在第6步中,b.com將cookie資訊返回給a.com伺服器,但是a.com伺服器並沒有把cookie資訊交給瀏覽器,所以瀏覽器最終沒能寫下b.com的cookie資訊。
由此可見,為啥header可以設定b.com的cookie,而curl不能設定b.com的cookie在於,header的時候,服務端把cookie資訊給了瀏覽器,而curl的時候,b.com把cookie給了a.com伺服器,並沒有給到瀏覽器,所以最終一個設定cookie成功,一個設定cookie失敗。