PHP網站中保持登入狀態的功能是怎麼做的?

來源:互聯網
上載者:User
關鍵字 Cookie
大多數網站在使用者登入時會提供一個“記住我”或者“保持登入狀態”的選項,我只知道是用Cookie實現的,但是具體來說的工作流程是什嗎?因為要實現一個網站登入的東西,所以想從細節方面瞭解這個問題。

回複內容:

我來談談這個問題吧
首先,基於以上幾位朋友提到的,SESSION資訊儲存在服務端,相對於儲存在用戶端的COOKIE更為安全,所以正常一般網站在用於“判斷使用者是否登入”時,確實是使用SESSION,例如可以在SESSION裡儲存如下一個數組
//驗證使用者名稱和密碼成功後$_SESSION['userinfo'] = [  'uid' => 123,  'username' => 'testuser'];
PHP中有cookie相關的函數, 使用者登入成功的時候,可能有如下的語句:
setcookie("user", "user1", time()+3600);

判斷使用者是否登入的時候,有類似這樣的語句:
if (isset($_COOKIE["user"])){
echo "已經登入";
}

使用者退出的時候,有類似這樣的語句:
setcookie("user", "", time()-3600);

如果使用者登入後一直沒點退出按鈕,3600秒之後,cookie也會失效。
如果想讓使用者保持足夠長的時間 time()+3600*24*365 就是登入後一年內都有效。看具體需求了,如果是本地記住那就直接用Cookie,把使用者名稱等資訊存起來,這就夠了。如果是一段時間內任何地方免登入那就用Session存在伺服器。然後當你訪問網站時直接判斷cookie或者session是否存在有效登入資訊。當然為了安全,你可以通過一些加密手段將使用者資訊加密之後再儲存起來。前面說的用user name作為session標識,存使用者資料每次請求從session取資料到資料庫校正,都是錯誤的做法。
第一個做法完全避免不了構造請求擷取使用者資料,也做不到靈活使用session,沒有登入的就沒有session資料?
第二個做法完全誤用session的作用,如果拿了session存的使用者帳號還要去資料庫取資料,那session存使用者帳號完全無意義。
此外退出瀏覽器並不會自動刪除網站cookie資料,非主動清除的情況下cookie的有效期間是根據set cookie的逾時時間值確定的,逾時才會清理。

1、sessionid是怎麼產生的,在接收請求之後,就需要判斷cookie是否提交sessionid參數,不存在則產生一個標識通過set cookie通知瀏覽器記錄sessionid。同時以此sessionid為標識存瀏覽器工作階段狀態所需的資料在伺服器。
這個操作與是否登入無關。任何請求都可設定這個操作。用於標識瀏覽器與伺服器的工作階段狀態。

2、如何?記錄使用者登入狀態,通常會在登入校正之後在cookie失效時間上面下功夫,而不是將使用者名稱密碼用任何形式儲存在用戶端或用戶端。比如在1步的情況下,set cookie通知瀏覽器此cookie失效時間為一個月,同時服務端的緩衝記錄登入狀態,失效時間也設定成一個月。

這樣只要瀏覽器不清理cookie,每一個請求服務端的參數都會自動把cookie裡面存的sessionid提交給服務端,這樣服務端可以通過get_session_info(sessionid)擷取工作階段狀態的敏感性資料,比如登入狀態,使用者名稱之類的資料。這樣就實現了登入狀態的儲存。

3、不建議做的事情
不建議在瀏覽器前端做任何記錄使用者個人資訊的操作,存個標識即可。
不建議在取session資料的時候做任何讀取資料庫的操作,使用session的目的就是把瀏覽器會話所需的資料緩衝,避免讀取資料庫。
不建議使用單個sessionid作為標識,像 左岸 的回答一樣,使用至少一個隨機字串作為校正標識,避免sessionid撞庫。各位大蝦好,我是只是說我自己的理解....

如果只用cookie的話貌似也可以實現登入功能,不過一般都是用session來實現登入吧?

在php中session_start之後就會產生一個session檔案,一般放在tmp目錄中,同時會設定一個用戶端的cookie,而這個cookie的值,其實就是隨機產生的session id,這樣一次會話也就建立了

這樣每次發送http請求的時候,伺服器就將cookie中獲得session id和那個session的檔案內容關聯起來了,php的程式中也就可以通過超級全域變數$_SESSION來獲得session資訊了

不過到目前為止,還只是一次會話的建立,不算是使用者登入,一般意義上的登入應該指的是把目前使用者的資訊和此次會話關聯起來,在php中一般就是,先通過使用者提交的使用者名稱和密碼進行驗證,將衍生後的資訊給$_SESSION賦值

我覺得這樣就是一次登入的過程吧,大概整理一下是:

1.session start 建立會話
2.通過使用者發送的使用者名稱密碼進行驗證,驗證成功則將使用者資訊與會話關聯

會話的建立讓伺服器始終知道這些請求是同一個使用者,使用者登入是讓伺服器知道這一直是哪一個使用者

究其原因還是因為http本身是無狀態協議,所以應用程式本身就要在兩頭儲存一些資訊進行狀態的確認

各位大蝦,一直以來我就是這麼實現的登入,自己也不知道有沒有什麼問題,如果有問題的話大俠們一定要指出啊,尤其是安全方面的

這樣省得我以後犯更嚴重的錯誤COOKIE由於儲存在用戶端,有被隨意篡改的風險,所以其實伺服器判斷使用者登陸狀態,一般都是用SESSION的...SESSION的資料存放區在伺服器中,但是必須通過用戶端的COOKIE來找到對應的SESSION
所以使用者登入的過程實際上是
1:使用者輸入使用者名稱密碼,POST資料到伺服器
2:伺服器判斷使用者名稱密碼是否正確,若正確,則在用戶端建立一個儲存SESSION_ID的COOKIE,並且在伺服器中建立一個相對應的SESSION_ID的SESSION,SESSION裡面的資料可能為使用者的資料
3:以後該使用者進行操作時,先從用戶端取出SESSION_ID,找到伺服器相對應的SESSION,取出資料,進行校正後再進行下一步操作..
然後說說我理解的保持登陸狀態
由於COOKIE儲存在用戶端,所以不建議用isset($_COOKIE['username'])來判斷使用者是否登陸.
因為使用者完全可以偽造一個COOKIE,來達到欺騙伺服器的目的...
那麼,我想到的兩種方法是:
1:上面有人說了,儲存username和加密的密碼,再次訪問時,伺服器取出COOKIE資料,與資料庫做校對,如果通過,則判斷為已經登陸
2:建立一個MySQL表,裡面存cookie_id,username,expire,time,然後每次登陸時,根據使用者選擇儲存登陸時間,來產生一個md5加密的cookie_id(可以用username,時間戳記和隨機數產生),然後將cookie_id,username,使用者保持的登陸時間,目前時間戳一起插入資料庫中,並且建立一個名為cookieid,值為上述md5加密的cookie_id的COOKIE.
那麼下一次使用者訪問時,伺服器可以先取COOKIE,根據COOKIE裡的cookieid找到相對應的資料庫中的資料,判斷有無合法COOKIE,有無生命週期等...如果全部通過就能判定為登陸了...
以上純為個人見解,如有不妥,請指教先說說結論:
1.cookie和session都可以用來保持登入狀態。
2.如果使用cookie,用於儲存使用者狀態的cookie需要加密,並且可被識別,但不必須可以解密。這個意思就是說,加密後的儲存了使用者登入資訊的cookie資料在服務端可被還原,即使不能還原也要可以用於識別和比對(即唯一),php的加密函數可以去網上找,一搜一大把。
3.如果使用session,在不考慮安全的情況下,可以簡單的使用$_SESSION這個全域數組達到目的,但是如果需要更高的安全性,需要額外的參數進行安全性驗證,可以是加密字串也可以是某串資料的MD5指紋。
4.使用session可以保證登入資料的一致性,如果登入資料中有在登入時間內可能會發生變動的項目,但是依然需要用到額外的參數去提取原來的session資料。
5.cookie比起session會有個滯後性,這一點需要注意,有時候有益,有時候也不方便。
6.在完全理解session的工作機制後,可以嘗試拋棄php本身的session機制,建立自訂session機制。

終極結論:
為了保證安全性,既然都需要加密cookie,那麼,為什麼不把使用者登入資料都儲存在cookie裡呢?session還會浪費伺服器端儲存。

終極進階結論:
當你學會使用記憶體資料庫的時候,比如memcached或者redis之類的,cookie和它們結合才是絕佳的解決方案。

下面扯點別的:

說起狀態維持這件事情,一直是http的痛處,因為http是無狀態協議,要讓無狀態協議支援狀態維持,於是產生了cookie,早期瀏覽器對cookie戒心甚大,於是勉為其難用一下GET參數也是無妨,現代瀏覽器都是預設開啟cookie的,甚至大部分都已經支援了瀏覽器端儲存(storage)以及少部分支援了瀏覽器端資料庫,後兩者僅是儲存,在請求時並不會向伺服器反饋資料。而session是建立在cookie或者其他從瀏覽器傳回的資料之上的,脫離了cookie或者其他從瀏覽器傳回的參數(比如GET參數)就是無源之水、無根之木。
有人說,甚至有不少人說,session比cookie安全,我覺得這是不恰當的看法。cookie和session具有同等的安全性,並不會因為cookie儲存於用戶端而session儲存於服務端而使cookie的安全性低於session,可以這麼說,cookie和session的安全性都取決於cookie或者前文提到的傳回伺服器的參數的安全性。
而且session也不僅僅是局限於php本身提供的session庫,任何儲存於伺服器端的資料都有可能扮演session的角色,本質上session是一種特殊的資料庫,只不過這個資料庫只允許已被識別的唯一合法用戶端去訪問。
雖然我在上面一段文字中強調了唯一,但是識別過程並不可靠,也就是有可能不唯一,這就是所謂的不安全性的來源。事實上,自從網路誕生以來,其上一直充斥的欺騙與暴力。這世上沒有任何事情是唯一的,就像沒有任何事物是完全相同的,雖然哲學一直教導我們世界上沒有兩件完全一樣的事物,也沒有兩件完全獨立的事物,但是這種絕對的觀念並不適合相對的生活。生活中,存在唯一這個概念,然而令人遺憾的是並沒有唯一的事實。即使有個枕邊人溫言細語的告訴你,你是他的唯一,如果你真信了,那隻能是你太天真。唯一這個事情是有分辨粒度的,在可被識別的範圍內,唯一才是有意義的,但是這種有意義卻著實令人心碎,可識別意味著判斷一個事物是否唯一的規則是有限的,有限就意味著可仿冒,時至今日,人類創造了各種用於識別唯一性的技術,但是關於識別技術,卻依然在發展,而且永無止境。

最後的最後,附贈幾段cookie操作函數:
特性1:去除了cookie的延時性,即設即用。
特性2:可以很方便的在cookie中儲存數組,不需要一條條的寫setcookie語句。
特性3:支援“.”索引,比如test.aaaa.bbbb是指cookie裡的test[aaaa][bbbb]。
注意1:千萬小心cookie的4kb限制,雖然有的現代瀏覽器可能擴充了這個限制。
注意2:cookie裡存太多東西畢竟增加了網路資料轉送以及伺服器的資料處理。

function set_cookie($data,$path = '/',$time = 0,$doma = NULL){if(!is_array($data)){$para = func_get_args();$data = array($para[0] => $para[1]);$path = isset($para[2]) ? $para[2] : '/';$time = isset($para[3]) ? $para[3] : 0;$doma = isset($para[4]) ? $para[4] : NULL;}if(is_int($path)){$time = $path;$path = '/';}if(is_string($time)){$doma = $time;$time = 0;}$time = $time == 0 ? $time : time()+$time;foreach($data as $key => $value){if(!is_array($value)){if(strpos($key,'.') === FALSE){if(isset($_COOKIE[$key])){if(is_array($_COOKIE[$key])){$cookie_str = http_build_query(array($key => $_COOKIE[$key]));$cookie_arr = explode('&',$cookie_str);foreach($cookie_arr as $cookie){$a_cookie = explode('=',$cookie);setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);}$_COOKIE[$key] = NULL;}}setcookie($key,$value,$time,$path,$doma);$_COOKIE[$key] = $value;}else{$cop = &$_COOKIE;$cox = substr_count($key,'.');foreach(explode('.',$key) as $ckk => $ckey){if($ckk > 0){$cookie_key .= '['.$ckey.']';}else{$cookie_key = $ckey;}if($ckk < $cox){if(isset($cop[$ckey])){if(!is_array($cop[$ckey])){setcookie($cookie_key,NULL,-1,$path,$doma);$cop[$ckey] = NULL;}}else{$cop[$ckey] = NULL;}$cop = &$cop[$ckey];}else{if(isset($cop[$ckey])){if(is_array($cop[$ckey])){$cookie_str = http_build_query(array($cookie_key => $cop[$ckey]));$cookie_arr = explode('&',$cookie_str);foreach($cookie_arr as $cookie){$a_cookie = explode('=',$cookie);setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);}$cop[$ckey] = NULL;}}else{$cop[$ckey] = NULL;}$cop = &$cop[$ckey];}}setcookie($cookie_key,$value,$time,$path,$doma);$cop = $value;}}else{$x_cookie_str = http_build_query($value);$x_cookie_arr = explode('&',$x_cookie_str);foreach($x_cookie_arr as $x_cookie){$a_cookie = explode('=',$x_cookie);if(isset($a_cookie[1])){set_cookie($key.'.'.str_replace(array('[',']'),array('.',''),urldecode($a_cookie[0])),urldecode($a_cookie[1]),$time,$path,$doma);}}}}}function cookie($key = NULL,$def = FALSE){if(!empty($key)){if(strpos($key,'.') === FALSE){if(isset($_COOKIE[$key])){return $_COOKIE[$key];}else{return $def;}}else{$cop = &$_COOKIE;foreach(explode('.',$key) as $ckey){if(isset($cop[$ckey])){$cop = &$cop[$ckey];}else{return $def;}}return $cop;}}else{return $_COOKIE;}}function unset_cookie($key = NULL,$path = '/',$doma = NULL){if(!empty($key)){if(strpos($key,'.') === FALSE){if(isset($_COOKIE[$key])){if(!is_array($_COOKIE[$key])){setcookie($key,NULL,-1,$path,$doma);}else{$cookie_str = http_build_query(array($key => $_COOKIE[$key]));$cookie_arr = explode('&',$cookie_str);foreach($cookie_arr as $cookie){$a_cookie = explode('=',$cookie);setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);}}unset($_COOKIE[$key]);}}else{$cop = &$_COOKIE;$ckeys = explode('.',$key);$pop_ckey = array_pop($ckeys);foreach($ckeys as $ckk => $ckey){if($ckk > 0){$cookie_key .= '['.$ckey.']';}else{$cookie_key = $ckey;}if(isset($cop[$ckey])){$cop = &$cop[$ckey];}else{return;}}if(isset($cop[$pop_ckey])){if(!is_array($cop[$pop_ckey])){setcookie($cookie_key.'['.$pop_ckey.']',NULL,-1,$path,$doma);}else{$cookie_str = http_build_query(array($cookie_key.'['.$pop_ckey.']' => $cop[$pop_ckey]));$cookie_arr = explode('&',$cookie_str);foreach($cookie_arr as $cookie){$a_cookie = explode('=',$cookie);setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);}}unset($cop[$pop_ckey]);}}}else{if(!empty($_COOKIE)){$cookie_str = http_build_query($_COOKIE);$cookie_arr = explode('&',$cookie_str);foreach($cookie_arr as $cookie){$a_cookie = explode('=',$cookie);setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);}$_COOKIE = array();}}}
雖然cookie和session都可以實現題主所想要的功能,但是更推薦使用session。
原因無他,只因為更安全,不容易被截獲偽造登入資訊。
// 登入成功後記錄登入資訊$_SESSION['loginStatus'] = array(    'username' => $username,    'status' => true,    'loginTime' = > time(),);...// 判斷session資訊if(empty($_SESSION['loginStatus']['status']) || !$_SESSION['loginStatus']['status']) {    // 引導到登入頁} else {    // 載入使用者資訊}
cookie和session我記得韓順平老師的視頻裡面,有一塊專門教寫登入模組的教程。
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.