改变用户session信息

做一个网站系统,用户每一次请求都要检查登录信息,而这些信息一般是保存在session或者cookie中,所以一般会判断session或者cookie中是否有数据来确定是否登录了。

遇到一种情况,就是在后台管理用户的时候,例如把某一个用户删除了,但是该用户只要还保留session数据的话还是能操作的。

针对这种情况,我想到两种办法:

1:每一次检查用户是否登录的时候要实时的查询表数据,不单单是检查session。
2:用数据库来保存用户的cookieId,当用户状态改变时候,修改对应的session数据。

不知道还有没有其他更好的办法来解决。欢迎交流,一起学习。

阅读 6.9k
8 个回答

先来复习一下session的基本原理:

a.生成过程:

用户在客户端输入用户名密登录 -> 服务器验证用户名密码正确 -> 服务器随机生成一个token(一般叫session_id) -> 服务端以session_id为主键(或key),绑定session数据(最基本就是uid,有时会加上基本的用户profile数据) -> 将session_id返回给客户端(一般是cookie)

b.使用:

 客户端带session_id访问(一般是cookie) -> 服务端根椐session_id查询session,如有,则认证成功,继续根椐session的内容(如uid)获取业务数据。 
  

再回到你的问题,其实你的思路基本是对的:

  1. 用户访问时,先查询session,如果已登录,再查uid是否存在 ,uid存在才认证成功。

    如果担心性能问题,可把uid直接用本地内存或memcache等缓存起来(删除用户时同时清除缓存,缓存丢了就重新登录)

  2. 保存session时,建立与uid的映射, 比如:
    如果session是存在关系数据库,那就 sid,session,将用户id作为session的值,那样,删除用户时就可以删除该用户的session
    如果session存在文件或者redis之类, 可以在生成session时同时建立反向映射关系保存,目的也是当后台删除用户时可以找到对应用户的session来删除

如果每次请求,频繁查询数据库并不理想。
常用过一个小技巧就是,写个定时ajax请求,如每隔5分钟检查一次。这种方法简单。
还有一种方法就是使用socket实现,如单点登陆原理一样实现

简单说一下我们的设计思路吧。我这边是每次请求,都会重新生成一个新的sessionId,返回给前端,前端将sessionId设置到header,每次请求将sessionId携带传递给服务端,服务端将获取sessionId进行对比,前端一般sessionId存储到localstorage或cookie中,服务端将sessionId一般存储到数据库或者缓存

我感觉这是个好问题。但是你提供的那两种方法个人认为不大好。我的思路是:使用共享式session解决这个问题。
所谓共享式session就是一个用户无论从任何终端登录,如果服务器端存在这个用户没有过期的session那么就把这个session的id返回给客户端,这样做的好处之一是多个终端可以共享服务器session中的数据。假设有一个新用户登录。那么怎么实现共享session呢?很简单,借助于memcache或者redis,以redis为例。(前提是你的session是存储在redis里的)
1.当用户登录成功后,通过user的id取一个hash,比如$key = md5($user->id)。以当前的session id为value,比如$value = session_id();然后把这个键值对存到redis中 Redis::set($key,$value);
2.等到一个用户再登录成功的时候,先用上个步骤的hash方法看看redis中存不存在$key = md5($user->id),如果不存在说明这是个新用户,然后为这个用户执行步骤1。如果存在就取出这个值$value = Redis::get($key),这个value就是该用户上一次登陆的session的id啊!
3.判断步骤2中取出的session id是否过期 Redis::ttl($value);如果没过期就直接返回给客户端,如果过期了或者不存在就创建一个新的session。

如果你使用共享session的方法,当你删除一个用户的时候,你可以根据Redis::get($key = md5($user->id)),得到这个用户的session id 然后根据这个session id删除session,这样他再请求服务器的时候浏览器带过来的cookie中的session id已经过期了。

新手上路,请多包涵

Session 总体来说还是安全的。
我觉得一个很简单的办法就是 Session 内保存用户 ID,在后端检查这个 ID 是否存在来判断是否登录。
或者也可以使用 Token 的方法,两个 Model:Token 和 User。
Token.uid reference User.id,保证删除用户的时候同时删除 Token。

session存储到redis,删除用户时找session数据中uid,有则删除key

删用户的时候把对应用户的session删除。

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

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏