在nodejs中使用express和express-session管理会话
什么是session
web是基于 HTTP 协议的, 而HTTP 是一种无状态协议,也就是说在每个请求和响应结束时,客户端和服务器不知道对方是谁。
这就是session的用处,session也叫做会话。允许服务器在多个请求之间维护用户的数据和状态,从而实现用户身份验证、保持登录状态、存储用户信息等功能。
session的工作机制
- 客户端(浏览器)发送首次请求到服务器。
- 服务器收到请求,发现客户端没有提供会话ID(缺少一个值为
session-id
的cookie)。 - 服务器创建一个新的会话,生成一个唯一的会话ID,并将其存储在
session-id
cookie 中,并将会话数据保存在后端存储中(例如内存、数据库等)。 - 服务器将会话ID作为响应的
Set-Cookie
头部发送回客户端,客户端浏览器会存储这个会话ID。 - 从此以后,客户端的每个请求都会附带这个会话ID的
session-id
cookie。 - 服务器根据收到的会话ID,从后端存储中查找相应的会话数据,以恢复用户的会话状态。
session和cookie的区别
cookie 是存储在浏览器中的键值对。浏览器会吧对应域名下面的 cookie 附加到发送到服务器的每个 HTTP 请求。
在 cookie 中,无法存储大量数据,cookie的大小通常受到浏览器对单个cookie大小和每个域名的cookie总数的限制,一般较小。最好不要吧敏感的数据比如用户信息存在cookie中。
session数据存储在服务器端,一般会放在数据库里面。因此,它可以容纳更大量的数据。session是通过在客户端cookie中存储会话ID,服务器使用这个ID查找对应的会话数据来实现。
开发环境设置
初始化package.json
$ npm init –y
安装express-session
在nodejs中管理session(会话),需要使用express-session这个中间件,可以使用下面的命令安装这个模块:
$ npm i express-session
安装express
要在 Node.js 中使用 express-session 模块设置会话,还需要安装 Express 模块:
$ npm i express
使用express-session
使用app.use(session(options))
就可以使用这个中间件,其中:
secret
是一个密钥,用来签名**session-id
**
resave
bool类型,默认为true,用于指定是否在每次请求时重新保存会话,即使会话在请求过程中从未被修改过。比如客户端向服务器发出两个并行请求,当第二请求结束时,对第一请求的会话所做的修改可能会被覆盖。
执行$node app.js
之后,我们使用curl命令来测试这个程序
$ curl -i localhost:3000
设置cookie的属性
上面例子可以看到session中间件帮我们设置了一个cookie,cookie的默认key为:connect.sid,
可以使用name字段设置cookie的key
还可以配置cookie的其他属性,如maxAge,secure等
使用session记录页面访问次数
上面的例子没有什么用处,这里我们来实现一个记录用户访问页面次数的例子:
当客户端第一次请求时,我们会给req.session写入一个views属性,当客户端再次发起请求时,会吧views加1,然后返回给客户端
使用curl请求:
$ curl -i localhost:3000
可以看到,响应的是’welcome to the session demo. please curl again!’
使用curl携带上一次的cookie再次请求:
$ curl -i -b "mycookie=s%3A_lsIhF-wH-IwuiUBeKcpqq_KIv1JVfFW.PVY28Bj0DhABROPOZM9h%2BY4gcbb7MVEyYqMu8lH73LI" localhost:3000
再次请求之后会响应用户访问的次数
使用session实现登陆退出功能
实现登录页面
登录页面是这样的:
login.html代码如下:
这个HTML登录表单,会使用POST方法将用户名和密码提交到服务器上的/login路由
处理根路由请求
跟路由请求会判断session里面是否有userid,如果有,则显示退出,否则显示登录页面
处理/login登录请求
这里我们用到了express.urlencoded中间件,这个中间件可以帮我们解析POST请求,并吧请求体的字段放在req.body里面
然后我们处理login请求,为了演示我们吧用户名和密码写死,用户名密码匹配之后,我们会吧username写入session
运行一下程序:
node app.js
输入用户名和密码登录之后可以看到登录成功,并且有了cookie,再次刷新页面,还会显示登录成功的页面,因为用户的信息已经被放在session里面
然后会到命令行可以看到打印的session如下:
实现/logout退出接口
我们直接调用session的destroy方法就可以实现退出
res.redirect是重定向功能,通过它会向用户返回一个 302 状态,通知 浏览器转向相应页面。
点击退出登录,我们就会回到首页,并且显示了登录页面
问题
可以看出登入和登出仅仅是 req.session.userid 变量的标记,非常简单。但这会不会有安全性问题呢?是不会的,因为这个变量只有服务端才能访问到,只要不是黑客攻破了整个服务器,无法从外部改动
完整代码地址:
https://github.com/AC-greener/nodejs-session
总结
这篇文章我们学会了使用session来管理会话,但是还有一些不足,我们的session是存在服务器内存的,当重启服务器时,session就没了,或着当有多台服务器时,会话状态也会出现不同步,所以一般会使用MongoDB或者Redis来存储会话,下一篇文章我们会使用到MongoDB~