禁用 COOKIE 後如何訪問 SESSION 問題

xiaoyukarl發表於2020-05-17

cookie和session有著千絲萬縷的關係

cookie和session區別

  • 儲存位置的不同
    cookie儲存在瀏覽器客戶端
    session儲存在服務端(可以是php伺服器,redis,資料庫)

  • 儲存的容量不同
    單個cookie儲存的資料<=4KB,一個站點最多儲存20個Cookie(瀏覽器不同而不同)。
    session原則上沒有限制,但是考慮到伺服器的效能,不宜儲存過多的資訊,並要有適當的刪除機制

  • 儲存資料格式不同
    cookie 只能保管ASCII字串,並需要透過編碼方式儲存為Unicode字元或者二進位制資料
    session 中能夠儲存任何型別的資料,包括且不限於string,integer,list,map等

  • 隱私策略不同
    cookie 對客戶端是可見的,別有用心的人可以分析存放在本地的cookie並進行cookie欺騙,所以它是不安全的。
    session 儲存在伺服器上,對客戶端是透明對,不存在敏感資訊洩漏的風險。

  • 有效期上不同
    程式可以透過設定cookie的過期時間,達到使cookie長期有效的效果。
    session 依賴於名為JSESSIONID的cookie,而cookie JSESSIONID的過期時間預設為-1,只需關閉視窗該session就會失效,因而session不能達到長期有效的效果。

  • 伺服器壓力不同
    cookie 保管在客戶端,不佔用伺服器資源。對於併發使用者十分多的網站,cookie是很好的選擇。
    session 是保管在伺服器端的,每個使用者都會產生一個session。假如併發訪問的使用者十分多,會產生十分多的session,耗費大量的記憶體。

  • 瀏覽器支援不同

    • 假如客戶端瀏覽器不支援cookie:
      cookie是需要客戶端瀏覽器支援的,假如客戶端禁用了cookie,或者不支援cookie,則會話跟蹤會失效。關於WAP上的應用,常規的cookie就派不上用場了。
      運用session需要使用URL地址重寫的方式。一切用到session程式的URL都要進行URL地址重寫,否則session會話跟蹤還會失效。

    • 假如客戶端支援cookie:
      cookie既能夠設為本瀏覽器視窗以及子視窗內有效,也能夠設為一切視窗內有效。
      session只能在本視窗以及子視窗內有效。

  • 跨域支援上的不同
    cookie支援跨域名訪問,例如將domain屬性設定為“.baidu.com”,則以“.baidu.com”為字尾的一切域名均能夠訪問該Cookie。跨域名Cookie如今被普遍用在網路中。
    而Session則不會支援跨域名訪問。Session僅在他所在的域名內有效。

當瀏覽器禁用cookie後如何獲取到session

我們知道,當在伺服器端啟用session時候,資料預設是以檔案的形式儲存伺服器上的,其中session_name(預設是PHPSESSID)和session_id是儲存在COOKIE中的,併傳送到Client端。此時,使用者訪問其他頁面傳送HTTP請求時候依然將cookie中儲存的session_name和session_id帶回伺服器端,而伺服器這時候同樣啟用了session,就會將session_id對應的檔案中儲存的資料反序列化並儲存到$_SESSION陣列中。整個流程大概是這樣子的。

有一天,客戶端無意將COOKIE禁用了,這時候再去伺服器端訪問上面流程的程式會出現這樣的情況。伺服器同樣會儲存session資料到檔案中(預設),但是設定的cookie頭資訊卻無法在客戶端儲存,後面再去訪問其他頁面時候客戶端也就沒有帶上cookie中的資料去傳送請求,然後伺服器也就無法獲取cookie資訊,造成的後果就是上次建立的session檔案成為了垃圾資料,而每次請求都要重新建立session檔案,然後一直迴圈~~ 無法跟蹤使用者登入狀態,造成不好的使用者體驗。

  • 透過php.ini設定來解決

    • 在瀏覽器開啟cookie時候使用cookie儲存會話資訊,當瀏覽器禁用cookie時候使用url傳遞會話資訊
      #在php.ini檔案中修改
      session.use_trans_sid=1  //啟用url傳遞會話資訊
      session.use_only_cookies=0  //關閉只是用cookie儲存會話資訊
      session.use_cookies=1   //預設使用cookie儲存會話資訊
    • 不管瀏覽器是否開啟cookie,都使用url的方式傳遞會話資訊
      #在php.ini檔案中
      session.use_trans_sid=1 //啟用url傳遞會話資訊
      session.use_only_cookies=0 //關閉只是用cookie儲存會話資訊
      session.use_cookies=0 //不使用cookie儲存會話資訊
      測試
      //set.php
      ini_set('session.use_trans_sid', 1);
      ini_set('session.use_only_cookies', 0);
      ini_set('session.use_cookies', 0);//全部使用url傳遞會話資訊
      session_start();
      $sid = session_id();
      $_SESSION['abc'] = ['value','value2'];
      echo '<a href="get.php">get</a>';
      //get.php
      session_id($_GET[session_name()]);
      session_start();
      var_dump($_GET[session_name()],$_SESSION, $_COOKIE);
      //可以獲取到session
  • 手動URL傳值
    為每個連結加上引數,引數值為session_id
    示例

    session_start();//啟動session
    $sid = session_id();
    $_SESSION['abc'] = ['value','value2'];//設定session
    $_SESSION['abc2'] = new stdClass();//設定session
    echo '<a href="get.php?sid='.$sid.'">get</a>';//將引數透過get的方式傳遞
    session_id($_GET['sid']);//獲取session_id, 必須在呼叫 session_start() 函式之前呼叫 session_id() 函式,否則無法使用該session_id
    session_start();//開啟session
    var_dump($_GET['sid'], $_SESSION);
  • 過隱藏表單傳遞
    在表單中隱藏提交session_id

  • 在資料庫中儲存session_id, 然後手動呼叫

Note: 基於 URL 的會話管理比基於 cookie 的會話管理有更多安全風險。例如使用者有可能透過 email 將一個包含有效的會話 ID 的 URL 發給他的朋友,或者使用者有可能在收藏夾中存有一個包含會話 ID 的 URL 來以同樣的會話 ID 去訪問站點。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章