摘要:基于以上原因,很多管理都是基于实现的。在经过中间件的时候就会自动完成的有效性验证延期重新颁发以及对中数据的获取了。上述代码只是对于请求的静态处理,整个用户管理的另一个方面则是状态的切换用户的登陆登出以及用户数据的获取。
基础概念
Session管理是Web Application的基础也是一个老生常谈的话题。为了方便后文的展开,更重要的是确认自己清晰的理解了整个Session管理的概念,我在此还是决定赘述的整个流程。如果你已经对于Session概念非常清晰的话,可以跳过本节不影响对于后文的理解。
HTTP协议在设计的时候是无状态的。这是一个很关键的概念,意味着服务器在处理请求的时候,并不关注这个请求是谁发来的。这对于以提供内容为核心的Web1.0,例如门户网站,非常适合。然而对于以应用服务为核心的Web 2.0而言,服务器端必须有能力从请求中提取出请求者的身份信息,以在请求者不用反复输入身份的情况下,提供连续的服务。
实现请求身份验证的方式很多,其中一种广泛接受的方式是使用服务器端产生的Session ID结合浏览器的Cookie实现对Session的管理,一般来说包括以下4个步骤:
服务器端的产生Session ID
服务器端和客户端存储Session ID
从HTTP Header中提取Session ID
根据Session ID从服务器端的Hash中获取请求者身份信息
上图是一个使用Redis Cluster来实现对Session管理的流程,但本质上除了redisMatrix.get和redisMatrix.set以外,和一般的Session管理流程是一致的。
简单来说,一个请求到达的时候,服务器会先判断是否带有Session信息。如果有,则根据Session ID去数据库中查找是否具有对应的用户身份信息。此处可能会出现Session失效、非法的Session信息等可能性,那么服务器视同无Ssession信息的情况,重新的产生一个随机的字符串,并且在Http返回头中写入新的Session ID信息。另一者,如果服务器成功获取了用户的身份信息则以该身份为请求者提供服务。
使用Express和Redis对Session管理的实现Redis是一个非常适合用于Session管理的数据库。第一,它的结构简单,key-value的形式非常符合SessionID-UserID的存储;第二,读写速度非常快;第三,自身支持数据自动过期和清除;第四,语法、部署非常简单。基于以上原因,很多Session管理都是基于Redis实现的。
Express已经将Session管理的整个实现过程简化到仅仅几行代码的配置的地步了,你完全不用理解整个session产生、存储、返回、过期、再颁发的结构,使用Express和Redis实现Session管理,只要两个中间件就足够了:
express-session
connect-redis
废话不多说还是上代码:
var express = require("express"); var session = require("express-session"); var RedisStore = require("connect-redis")(session); var app = express(); var options = { "host": "127.0.0.1", "port": "6379", "ttl": 60 * 60 * 24 * 30, //Session的有效期为30天 }; // 此时req对象还没有session这个属性 app.use(session({ store: new RedisStore(options), secret: "express is powerful" })); // 经过中间件处理后,可以通过req.session访问session object。比如如果你在session中保存了session.userId就可以根据userId查找用户的信息了。
req在经过session中间件的时候就会自动完成session的有效性验证、延期/重新颁发、以及对session中数据的获取了。
上述代码只是对于请求的Session静态处理,整个用户管理的另一个方面则是状态的切换(用户的登陆、登出)以及用户数据的获取。
exports.signin = function(params, req, res){ var username = params.username; var password = params.password; //查找用户信息,看是否满足登陆条件 var user = findUser(username, password); if(user){ //成功获取用户对象 req.session.regenerate(function(){ req.user = user; req.session.userId = user.id; req.session.save(); //保存一下修改后的Session res.redirect("/account"); }); } else{ //用户信息不符合,登陆失败 } } exports.signout = function(req, res){ req.clearCookie("connect.sid"); req.user = null; req.session.regenerate(function(){ //重新生成session之后后续的处理 res.redirect("/signin"); }) } exports.persist = function(req, res, next){ var userId = req.session.userId; //通过user id去数据库里面查找User对象 var user = findUserById(userId); if(user){ req.user = user; next(); } else{ //该用户不存在 } }Session的安全问题
SessionId就如同请求者的身份证,一旦被攻击者恶意获得,攻击者便可以伪装成请求者对服务器发起请求,也就是我们经常听到的会话劫持(Session/Cookie Hijack)
关于会话劫持的原理推荐大家去看这篇文章
基于上述实现方法的Session管理,我认为基本上可以排除
暴力破解SessionId
恶意植入固定SessionId
两种可能,因为uid的库基本上可以保证SessionId的随机性;而传递SessionId则依赖HTTP请求头中的Cookie信息而非URL,同时在用户登录立刻更换SessionId。
唯一的可能性来源于Session的监听,而对于这种攻击有效的两种防止办法是:
Https
很多网站仅仅在Login的阶段使用Https防止用户的用户名、密码信息被监听者获取,但是随后的SessionId同样有可能被监听者获取而伪造登录者的身份信息。因此更加推荐的方式是所有的信息传递全部使用Https实现,这样即使监听着截获了信息也无法破解其中的内容。关于如何使用NodeJS建立一个HTTPS的server可以参考《HTTPS的原理和NodeJS的实现》 这篇文章
httpOnly
Express在options中提供了httpOnly的属性,此属性默认值为true,这个属性保证了Cookie的信息不能够通过JavaScript脚本获取。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85588.html
世界上任何一个拥有用户数据的 web 应用都必须处理 sessions。作为一名开发者,我们必须要知道它们是什么以及如何处理它们。在这篇文章中,我想要分享的是: session 是什么? session 如何存储数据? 你如何决定存放 session 数据的位置? 在 sessions 工作时,你必须意识到的安全性上的影响有哪些?在一些示例代码中,我将会运用 session npm modul...
摘要:当会话过期或被放弃后,服务器将终止该会话。原来中间件生成的是一个对象,里面包含了信息。这个有一个过期时间,比如,上面代码中设置的是小时。也就是说,小时后,这个在浏览器中会自动消失。 前言 在上一篇中node中的cookie,对cookie进行了相关介绍,本篇将继续前行,对session进行说明。 session是什么 session不就是会话嘛,那什么是会话呢?会话是一个比连接粒度更大...
摘要:当会话过期或被放弃后,服务器将终止该会话。原来中间件生成的是一个对象,里面包含了信息。这个有一个过期时间,比如,上面代码中设置的是小时。也就是说,小时后,这个在浏览器中会自动消失。 前言 在上一篇中node中的cookie,对cookie进行了相关介绍,本篇将继续前行,对session进行说明。 session是什么 session不就是会话嘛,那什么是会话呢?会话是一个比连接粒度更大...
阅读 3747·2021-11-11 11:02
阅读 3465·2021-10-11 10:57
阅读 3579·2021-09-22 16:00
阅读 1823·2021-09-02 15:15
阅读 1283·2019-08-30 15:56
阅读 985·2019-08-30 15:54
阅读 2707·2019-08-30 12:43
阅读 3510·2019-08-29 16:06