基于session实现用户登录?
问题描述
最近在研究基于session实现用户登录的功能时,突然对 服务端session校验的过程感到疑惑,之前都是通过拿到cookie中的sessionid然后通过session!=null
去判断用户是否登录
那么问题来了,session是如何对不同的用户session有效性进行校验的?
以一个简单的登录网站举例,如果说用户A,没有注册但是通过浏览器的控制台在cookie里面随便编了一个JSESSIONID,这种情况下如果只看session是不是并不能判断出这个用户的真伪。
换句话说,sessionid只存在于用户浏览器的cookie中,而后端只是判session是否为空而不会去校验sessionid是后端生成的还是用户自己编造的?
另外如果A、B两个不同用户通过同一个session(比如都是A用户或者自己编的)都会判定其登录?而不会在意这个session是哪个用户的?
其实比较疑惑的地方就是在学这部分知识的时候,包括很多有关博文都说, 实现的原理是用户登录以后后端会生成一个唯一的sessionid存放在用户浏览器的cookie中,用户登录以后做的所有需要鉴权的操作都会先把之前的sessionid传回后端进行校验但是几乎没有博文有说sessionid传回后端以后是怎么通过sessionid找到对应的用户并进行校验的
想的很好。但有一个误区。
首先 Session 无论是集中式还是分布式的,一定是存储在某个地方的。你可以想象成它是一个字典结构,而 SessionId 仅仅是一个 Key 而已。判断会话是否有效(也就是你所谓的用户是否登录)实际上是先判断 SessionId 是否在这个字典中存在、进而继续其他逻辑。而不是简单地看客户端传没传 SessionId 这个值。
换而言之,逻辑其实是:
boolean isLoggedIn = sessionMap.get(sessionId) != null;
而不是:
boolean isLoggedIn = sessionId != null && !sessionId.isEmpty();
当然了,这部分逻辑通常已经封装在你所使用的 Web 框架内部了。
那么问题就在于如何防止客户端伪造一个 SessionId、恰好这个值是有效的。这种攻击方式有一个专门的词来形容,叫“Session Prediction Attack”(Session 猜测攻击),你会看到有一些企业内网被攻破的案例中黑客就是采用了这种攻击方式。而对抗它的通常就那么几招:
- 确保 SessionId 的生成结果尽可能是离散的,这样就无法通过多个 Session 找出碰撞规律。
- 确保 SessionId 的长度足够,十年前的安全类文章会建议你 128 个字节,今天的话这个值再翻两倍也不为过。
- 确保 Session 的有效期不要太长(注意是 Session 的有效期、而不是 Cookies 的有效期,这两者是有区别的)。
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容