1. 程式人生 > >cookie系列(二)header302跳轉引發的思考

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失敗。