使用COOKIE實現登陸 VS 使用SESSION實現登陸

注:本文使用的代碼基於PHP,其餘語言邏輯同理。php

 

一:使用COOKIE實現登陸驗證linux

使用cookie實現登陸的方式,主要經過一些單向的加密信息進行驗證。好比admin用戶登陸了以後,服務端生成一個cookie值:admin_1533006028_ bbf2c2b1ec5cfb62d0a30438d8d0305c ,這個cookie值包含用戶名,cookie到期時間和一個信息簽名。簽名的信息爲 」用戶名_用戶密碼_cookie到期時間_鹽」 好比:md5(」admin_1533006028_123456_salt123」)。這樣用戶每次訪問,只要獲取到這個cookie值,而後驗證cookie到期時間和簽名。就能夠判斷該用戶是否已登陸。redis

首先看看下面cookie登陸的實例代碼:數據庫

<?php
class Login { //登陸 public function login($account,$password) { $lifetime = time()+3600; $model = new Model(); $pwd = md5($password); $userInfo = $model->db->getOne(array(‘username’=>$username,’password’=>$pwd); if($userInfo){ $cookie =$this->user2cookie($userInfo, $lifetime); setcookie('account', $cookie, $lifetime); return true; }else{ return false; } } //驗證登陸 public static function isLogin() { $cookie = $_COOKIE['account']; $re = $this->cookie2user($cookie); return $re; } //根據cookie判斷一個用戶是否合法的登陸用戶 public function cookie2user($cookie) { if(empty($cookie)) return false; list($username,$lifetime,$token) = explode('_',$cookie); //cookie過時或者cookie1分鐘內過時 if($lifetime < (time()+60)) return false; $model = new Model(); //獲取緩存中的用戶信息 $userInfo = $model->redis->get($username); if(!$userInfo){ $userInfo = $model->db->getOne(array(‘username’=>$username)); }else{ $userInfo = parse_url($userInfo); } if(!$userInfo){ return false; } //驗證token值 $str = $username.$userInfo['password'].$lifetime.$userInfo[‘salt’]; if($token !== md5($str)) return false; $val = http_build_query($userInfo , '' , '&'); //將用戶信息設置到緩存中,鍵值生命週期爲1小時。 $model->redis->set($username,$val,3600); return true; } //生成驗證用戶登陸的cookie值 public function user2cookie($user,$lifetime) { $str = $user['username'].$user['password'].$lifetime.$user[‘salt’]; $token = md5($str); $re = $user['username'].'_'.$lifetime.'_'.$token; return $re; } } ?>

 

cookie的登陸流程: 首先經過Login() 函數驗證用戶提交的用戶名和密碼,若是驗證經過則將相關信息寫入cookie, 後面使用isLogin() 函數對用戶的每次訪問進行驗證,驗證的方式也是經過該用戶的cookie。驗證經過則說明該用戶已經登陸,不然說明該用戶沒有登陸。跳轉到登陸頁面。瀏覽器

這裏重點講下Login類的兩個關鍵函數cookie2user和user2cookie:緩存

一、  cookie2user根據cookie判斷一個用戶是否合法的登陸用戶,即用戶每次訪問,都會經過isLogin函數驗證該用戶是否已經登陸。驗證方式就是獲取到用戶這次訪問的cookie值,而後將驗證cookie值裏的token(簽名信息)值。驗證經過,說明該用戶是已經登陸的,不然就是爲登陸或者不存在該用戶。服務器

二、  user2cookie用於生成驗證用戶登陸的cookie值。如前文所述,該cookie值包含用戶名、cookie生存時間和token值。這裏關鍵就是這個token值的生成方式,要注意判斷登陸的時候生成token值的方式要與此函數生成token值的方式一致。好比這裏是將用戶名,用戶密碼,cookie生存時間和鹽進行鏈接並取md5值。固然加密方法也能夠不用md5,也可使用sha1等。cookie

 

2、使用SESSION實現登陸驗證session

因爲session的信息是保留在服務端的,因此用戶登陸戶的信息保存在服務,因此無需像cookie登陸的那樣將信息進行單向加密。分佈式

session登陸的示例代碼:

<?php

class Login
{
   //登陸
   public function  login($account,$password)
   {
        $model = new Model();
        $pwd = md5($password);
        $userInfo = $model->db->getOne(array(‘username’=>$username,’password’=>$pwd);
        if($userInfo){
           $_SESSION[‘account’] = $userInfo;
           return true;
        }else{
            return false;
        }
    }

 
    //驗證登陸
    public static function isLogin()
    {
         if(isset($_SESSION['account'])){
                return true;
         }else{
                return false;
         }
    }

}

?>    

 

session的登陸流程:首先用戶提交的用戶名和密碼提交到Login() 方法進行驗證,若是驗證經過則將信息寫入session,後面每次訪問都會去取該用戶的session信息。若是不存在該用戶的SESSION信息,則說明該用戶尚未登陸,跳轉到登陸頁面。已經登陸了的用戶每次訪問,都會經過isLogin() 函數進行驗證。驗證不經過說明登陸過時或者沒有登陸,則跳轉到登陸頁面。

兩種方式都是經過isLogin() 方法來驗證用戶是否已經登錄的了。該方法通常在程序的入口處進行Login::isLogin() 調用,從而對全部的訪問進行驗證。

 

3、兩種方式的異同點

除了上文已經簡述的以外,這裏先介紹下PHP裏面處理SESSION的機制。

PHP在調用seesion_start() 函數以後會生成一個字符串(通常是某些不重複的哈希值)。這個字符串就是session_id,固然這個值也能夠自行調用函數session_id(‘指定的session_id 值’)進行構建,須要注意的是,session_id()函數必須在session_start() 函數以前先調用。只有調用了session_start() 函數,纔會產生相應的session文件和cookie值。

具體過程以下:

一、客戶端(瀏覽器)首次訪問時,這裏默認開啓了session_start() 函數的,此時PHP會隨機生成一個不重複的cookie(即session_id,這裏假如生成ug9gch0ns7nql4gjoe3jckdab2)值。

 

二、服務端會生成一個session文件默認文件名爲’SESS_’.session_id,即:SESS_ ug9gch0ns7nql4gjoe3jckdab2 文件。文件的保存路徑默認在php.ini的session.save_path設置的路徑中,例如linux系統中默認爲/var/lib/php/sessions目錄。(注意:此時SESS_ ug9gch0ns7nql4gjoe3jckdab2文件是個空文件,由於服務端尚未信息存入SESSION中,具體看第4步)

 

三、而後將生成的 ug9gch0ns7nql4gjoe3jckdab2 設置到cookie裏,cookie鍵名默認是php.ini裏設置的session.name配置項,默認是:session.name=PHPSESSID;至關於執行了$_COOKIE[‘PHPSESSID’]= ug9gch0ns7nql4gjoe3jckdab2;用戶這次訪問的http響應頭部信息裏就會包含:

Set-Cookie: PHPSESSID=ug9gch0ns7nql4gjoe3jckdab2; path=/

相應的cookie信息就會保存到客戶端。

 

四、用戶在登陸界面輸入用戶名和密碼並提交。此時瀏覽器會將用戶名和密碼和cookie值等信息提交到服務端。此時http請求的頭部信息會包含:Cookie:PHPSESSID=ug9gch0ns7nql4gjoe3jckdab2

 

五、當數據到達服務端,PHP會根據cookie內容找到session文件SESS_ ug9gch0ns7nql4gjoe3jckdab2 並將該文件讀入$_SESSION 變量。而後驗證用戶名和密碼。驗證經過了。就將該用戶的相關信息,好比用戶名、系統權限等寫入到$_SESSION 變量中。cookie沒有改變。腳本執行結束時,$_SESSION變量的值會被序列化後寫入SESS_ ug9gch0ns7nql4gjoe3jckdab2 文件。

驗證不經過,則跳轉回登陸頁,cookie沒有改變,$_SESSION也沒有新增值。

 

六、若是用戶完成登陸進入系統了,之後每訪問一個頁面,系統會獲取該客戶端瀏覽器傳過來的cookie值,而後根據cookie值獲取到對應的session文件,讀取session文件並解序列化寫入到內存中即$_SESSION變量中。接着服務端系統接口處會驗證該$_SESSON文件中是否有以前設置的用戶信息,如用戶名和系統權限等。若是有,則說明該用戶已經登陸,若是沒有,則說明該用戶登陸過時或者未登陸,跳轉到登陸頁面。

 

使用cookie來實現登陸就不會再使用到session了。如文章開頭所述,cookie實現登陸須要將用戶的信息進行單向加密。而後經過驗證該密文確認用戶是否已經登陸。也許你們會感受使用session驗證登陸的步驟比cookie的簡單許多。其實只是須要咱們處理的步驟比較少而已,有一部分是語言編譯器內部實現的。好比session文件的生成匹配。因此到咱們本身操做的步驟就會相對較少。cookie實現登陸主要依靠單向加密驗證,好比用戶登陸時對」用戶名+用戶密碼+cookie過時時間+鹽」這些信息進行md5簽名,而後將該簽名放到cookie中,固然cookie值還包含用戶名和cookie值的過時時間,好比:admin_1533006028_ bbf2c2b1ec5cfb62d0a30438d8d0305c。後面用戶每次訪問都獲取到這個cookie值,拆分後根據用戶名和cookie值的過時時間,加上從數據庫獲取的用戶密碼和鹽值,進行md5簽名,而後對兩步簽名進行比對,若是一致,則說明是已登陸的用戶。

 

因爲用戶每次訪問都要驗證cookie裏的簽名,也就是每次都要獲取用戶密碼和鹽值。通常這些信息都是存在數據庫中。因此使用cookie實現登陸,會對數據庫的用戶表形成極大的壓力。而session方式則不存在這個問題,由於session是存在文件中,用戶每次訪問,PHP會將該用戶對應的session文件讀入內存。而後再去訪問$_SESSION變量獲取。可是session這樣處理的缺點是,當用戶量特別多的時候,每一個用戶都會產生一個session文件,這意味着服務器的壓力倍增。就算作分佈式,也還要處理session的集羣。

 

固然,session也能夠寫入數據庫,或者寫入緩存。若是session寫入數據庫,那麼又回到剛纔cookie每次訪問都要查詢數據庫的問題了。若是是寫入緩存,倒也是權宜之計。若是在使用cookie登陸的步驟中將用戶信息寫入緩存,那麼這種方式也能夠減緩數據庫的壓力。每次驗證時若是緩存中沒有再去查詢數據庫。這樣也不失爲一個可行之計。

 

固然,也能夠對用戶表進行分表並做一主庫多從庫處理。在大用戶量狀況下,單使用數據庫,應該也能支撐吧。

相關文章
相關標籤/搜索