鍍金池/ 問答/PHP/ 改變用戶session信息

改變用戶session信息

做一個網(wǎng)站系統(tǒng),用戶每一次請求都要檢查登錄信息,而這些信息一般是保存在session或者cookie中,所以一般會判斷session或者cookie中是否有數(shù)據(jù)來確定是否登錄了。

遇到一種情況,就是在后臺管理用戶的時候,例如把某一個用戶刪除了,但是該用戶只要還保留session數(shù)據(jù)的話還是能操作的。

針對這種情況,我想到兩種辦法:

1:每一次檢查用戶是否登錄的時候要實時的查詢表數(shù)據(jù),不單單是檢查session。
2:用數(shù)據(jù)庫來保存用戶的cookieId,當(dāng)用戶狀態(tài)改變時候,修改對應(yīng)的session數(shù)據(jù)。

不知道還有沒有其他更好的辦法來解決。歡迎交流,一起學(xué)習(xí)。

回答
編輯回答
念初

Session 總體來說還是安全的。
我覺得一個很簡單的辦法就是 Session 內(nèi)保存用戶 ID,在后端檢查這個 ID 是否存在來判斷是否登錄。
或者也可以使用 Token 的方法,兩個 Model:Token 和 User。
Token.uid reference User.id,保證刪除用戶的時候同時刪除 Token。

2017年4月11日 00:52
編輯回答
苦妄

session存儲到redis,刪除用戶時找session數(shù)據(jù)中uid,有則刪除key

2017年3月2日 13:43
編輯回答
夢若殤

先來復(fù)習(xí)一下session的基本原理:

a.生成過程:

用戶在客戶端輸入用戶名密登錄 -> 服務(wù)器驗證用戶名密碼正確 -> 服務(wù)器隨機(jī)生成一個token(一般叫session_id) -> 服務(wù)端以session_id為主鍵(或key),綁定session數(shù)據(jù)(最基本就是uid,有時會加上基本的用戶profile數(shù)據(jù)) -> 將session_id返回給客戶端(一般是cookie)

b.使用:

 客戶端帶session_id訪問(一般是cookie) -> 服務(wù)端根椐session_id查詢session,如有,則認(rèn)證成功,繼續(xù)根椐session的內(nèi)容(如uid)獲取業(yè)務(wù)數(shù)據(jù)。 
  

再回到你的問題,其實你的思路基本是對的:

  1. 用戶訪問時,先查詢session,如果已登錄,再查uid是否存在 ,uid存在才認(rèn)證成功。

    如果擔(dān)心性能問題,可把uid直接用本地內(nèi)存或memcache等緩存起來(刪除用戶時同時清除緩存,緩存丟了就重新登錄)

  2. 保存session時,建立與uid的映射, 比如:
    如果session是存在關(guān)系數(shù)據(jù)庫,那就 sid,session,將用戶id作為session的值,那樣,刪除用戶時就可以刪除該用戶的session
    如果session存在文件或者redis之類, 可以在生成session時同時建立反向映射關(guān)系保存,目的也是當(dāng)后臺刪除用戶時可以找到對應(yīng)用戶的session來刪除
2018年1月24日 05:19
編輯回答
淚染裳

刪用戶的時候把對應(yīng)用戶的session刪除。

2017年8月8日 19:00
編輯回答
伐木累

如果每次請求,頻繁查詢數(shù)據(jù)庫并不理想。
常用過一個小技巧就是,寫個定時ajax請求,如每隔5分鐘檢查一次。這種方法簡單。
還有一種方法就是使用socket實現(xiàn),如單點登陸原理一樣實現(xiàn)

2017年7月20日 17:15
編輯回答
傻丟丟

我感覺這是個好問題。但是你提供的那兩種方法個人認(rèn)為不大好。我的思路是:使用共享式session解決這個問題。
所謂共享式session就是一個用戶無論從任何終端登錄,如果服務(wù)器端存在這個用戶沒有過期的session那么就把這個session的id返回給客戶端,這樣做的好處之一是多個終端可以共享服務(wù)器session中的數(shù)據(jù)。假設(shè)有一個新用戶登錄。那么怎么實現(xiàn)共享session呢?很簡單,借助于memcache或者redis,以redis為例。(前提是你的session是存儲在redis里的)
1.當(dāng)用戶登錄成功后,通過user的id取一個hash,比如$key = md5($user->id)。以當(dāng)前的session id為value,比如$value = session_id();然后把這個鍵值對存到redis中 Redis::set($key,$value);
2.等到一個用戶再登錄成功的時候,先用上個步驟的hash方法看看redis中存不存在$key = md5($user->id),如果不存在說明這是個新用戶,然后為這個用戶執(zhí)行步驟1。如果存在就取出這個值$value = Redis::get($key),這個value就是該用戶上一次登陸的session的id啊!
3.判斷步驟2中取出的session id是否過期 Redis::ttl($value);如果沒過期就直接返回給客戶端,如果過期了或者不存在就創(chuàng)建一個新的session。

如果你使用共享session的方法,當(dāng)你刪除一個用戶的時候,你可以根據(jù)Redis::get($key = md5($user->id)),得到這個用戶的session id 然后根據(jù)這個session id刪除session,這樣他再請求服務(wù)器的時候瀏覽器帶過來的cookie中的session id已經(jīng)過期了。

2017年9月27日 14:07
編輯回答
扯機(jī)薄

簡單說一下我們的設(shè)計思路吧。我這邊是每次請求,都會重新生成一個新的sessionId,返回給前端,前端將sessionId設(shè)置到header,每次請求將sessionId攜帶傳遞給服務(wù)端,服務(wù)端將獲取sessionId進(jìn)行對比,前端一般sessionId存儲到localstorage或cookie中,服務(wù)端將sessionId一般存儲到數(shù)據(jù)庫或者緩存

2017年10月1日 14:39
編輯回答
誮惜顏

自己想到一個方法,不知道可行不。歡迎交流。
就是保存的session文件名都是有sessionID的,那么只要保存好sessionID,直接使用unlink去刪除那個文件,可否?

2018年4月28日 18:18