session儲存資料庫中以及禁用cookie情況下的處理

zealyw發表於2019-02-16

什麼是session

HTTP協議是無狀態的,我們在瀏覽一個網站的時候 網站並不知道你是誰,為了解決這一點於是有了==會話管理==
會話管理主要包括cookie和session。cookie可以在客戶端記錄下資訊,而session則是記錄資訊在伺服器上。典型的應用場景:當我們登入一個網站,我們的登入資訊就會存放在session當中,接下來在一些需要使用者登入下才能操作的地方就可以通過session來判斷使用者的合法性。使用者每次登入得到的==會話ID==是唯一的,這個會話ID可以儲存在客戶端中或者進行網路傳輸。客戶端也就可以通過cookie或者url傳輸來傳遞這個會話ID獲取存在伺服器上的session資訊

session的原理

當程式需要為某個客戶端的請求建立一個session的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個session標識-稱為sessionid,如果已包含一個sessionid則說明以前已經為此客戶端建立過session,伺服器就按照sessionid把這個session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含sessionid,則為此客戶端建立一個session並且生成一個與此session相關聯的sessionid,sessionid的值應該是一個既不會重複,又不容易被找到規律以仿造的字串,這個sessionid將被在本次響應中返回給客戶端儲存。儲存這個sessionid的方式可以採用cookie,這樣在互動過程中瀏覽器可以自動的按照規則把這個標識發揮給伺服器。

存放session資料到資料庫中

session的預設存放是通過建立一個名為sessionID的檔案進行存放。
使用MySQL儲存session會話較files有很多優點:
1) 有利於分散式系統,files只能儲存在一臺機器上
2) 有利於大訪問量的系統,使用files時每個session儲存在一個檔案中,目錄會超級大,查詢session檔案會比較困難。

禁用cookie的影響

由於cookie可以被人為的禁止,服務端就無法在使用者本地儲存session id,我們需要一種變通的方法來實現session機制。

實現過程

  • 更改php.ini檔案。
    找到

//php預設儲存session的方式
session.save_handler=files
//使用cookie(session cookie)來儲存session id
session.use_cookies = 1
//只使用session cookie來儲存session id。
session.use_only_cookies = 1
//session cookie的名稱為PHPSESSID。
session.name = PHPSESSID
//seesion cookie的生存週期,預設情況下,瀏覽器一旦關閉,session就會被銷燬
session.cookie_lifetime = 0
//讓PHP自動跨頁傳遞session id
session.use_trans_sid = 0; 

修改為

//把session的模式改成使用者自定義
session.save_handler=user
session.use_cookies = 0
session.use_only_cookies = 0
//讓PHP自動跨頁傳遞session id
session.use_trans_sid = 1
  • 通過session_set_save_handler() 設定使用者自定義會話儲存函式

測試程式碼

//Database
CREATE TABLE `Session` (
  `Session_Id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `Session_Expires` datetime NOT NULL,
  `Session_Data` text COLLATE utf8_unicode_ci,
  PRIMARY KEY (`Session_Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
SELECT * FROM mydatabase.Session;

session.php

<?php
date_default_timezone_set(`Asia/Shanghai`);

class SysSession implements SessionHandlerInterface
{
    private $link;

    public function open($savePath, $sessionName)
    {
        $link = mysqli_connect("localhost","root","","xiaoshuo");
        if($link){
            $this->link = $link;
            return true;
        }else{
            return false;
        }
    }
    public function close()
    {
        mysqli_close($this->link);
        return true;
    }
    public function read($id)
    {
        $result = mysqli_query($this->link,"SELECT Session_Data FROM Session WHERE Session_Id = `".$id."` AND Session_Expires > `".date(`Y-m-d H:i:s`)."`");
        if($row = mysqli_fetch_assoc($result)){
            var_dump($row);
            return $row[`Session_Data`];
        }else{
            return "";
        }
    }
    public function write($id, $data)
    {
        $DateTime = date(`Y-m-d H:i:s`);
        $NewDateTime = date(`Y-m-d H:i:s`,strtotime($DateTime.` + 1 hour`));
        $result = mysqli_query($this->link,"REPLACE INTO Session SET Session_Id = `".$id."`, Session_Expires = `".$NewDateTime."`, Session_Data = `".$data."`");
        if($result){
            return true;
        }else{
            return false;
        }
    }
    public function destroy($id)
    {
        $result = mysqli_query($this->link,"DELETE FROM Session WHERE Session_Id =`".$id."`");
        if($result){
            return true;
        }else{
            return false;
        }
    }
    public function gc($maxlifetime)
    {
        $result = mysqli_query($this->link,"DELETE FROM Session WHERE ((UNIX_TIMESTAMP(Session_Expires) + ".$maxlifetime.") < ".$maxlifetime.")");
        if($result){
            return true;
        }else{
            return false;
        }
    }
}
$handler = new SysSession();
session_set_save_handler($handler, true);
?>

page1.php

<?php
ini_set("session.use_cookies", 0);
ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 1);
date_default_timezone_set(`Asia/Shanghai`);

require_once(`session.php`);

session_start();

$_SESSION[`var1`] = "Just Test";
echo "<a href=`page2.php`>測試</a>";
?>

page2.php

<?php
ini_set("session.use_cookies", 0);
ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 1);
date_default_timezone_set(`Asia/Shanghai`);

require_once(`session.php`);

session_start();

if(isset($_SESSION[`var1`])){
    echo $_SESSION[`var1`];
}
?>

相關文章