Express.js(Node.js) 配置Redis持久化存储Session会话

 2016年03月06日    1302     声明


Session用于在服务端保存用户会话状态(如:用户登录信息等)。Session在程序重启、多进程运行、负载均衡、跨域等情况时,会出现Session丢失或多进程、多个负载站点间状态不能共享的情况。要解决这些问题,我们需要将Session持久化存储,Redis存储是一个非常不错的Session持久化解决方案。


  1. SessionCookie
  2. Express.js配置Redis存储

HTTP是一种无状态的协议。在HTTP协议中,制定了Cookie机制,用于实现客户端和服务器之间的状态共享。

Cookie存储在客户端,因此也带来一些问题,如:Cookie很容易在客户端被修改、随着Cookie数据量的增加会造成与服务器传输效率的降低。

Session要配合Cookie实现,Session解决了Cookie中的一些问题。其数据存储在服务端,而只在Cookie中存储一个SessionId,这样就有效的避免了数据在客户端的修改,增加了数据的安全性,同时也减少了客户端与服务端交互时的数据量。

Session是一种不错的保持客户端与服务端会话状态的解决方案,但Session也有缺陷。Session在服务器端是存储在内存中的,这样势必会造成其易失性,也不能在不同进程和不同站点间共享状态。所以,我们需要借助Redis等存储方式将Session持久化存储。


2. Express.js配置Redis存储

接下来,我们通过一个实例来介绍在Express中配置使用Redis持久化存储Session

使用Redis持久化存储Session的前提是已经安装好Redis,全新安装Redis请参考:Linux安装配置Redis CentOS下安装Redis。要在Express中使用,还需要创建一个Express项目,创建Express详细说明请参考:Express.js 创建Node.js Web应用。我们假设已经完成了前面两项工作,下面的只介绍在Express项目配置Redis的方法。


2.1 安装Redis模块

在Node.js中访问Redis需要借助redisconnect-redis模块来实现Redis的连接,Express默认没有安装这两个模块,安装命令如下:

npm install redis connect-redis --save


2.2 安装Session处理模块

安装完redisconnect-redis两个模块后,就可以在Node.js中访问Redis,要实现Session的持久化存储还需要express-session模块,该模块用于Session设置、读取等操作:

npm install express-session --save


2.3 Redis存储配置

安装完所需模块后,在Express项目的app.js中配置好相关中间件即可。

引入相关模块:

var expressSession = require('express-session');
var redis = require('redis');
var RedisStore = require('connect-redis')(expressSession);

配置存储:

// 创建Redis客户端
var redisClient = redis.createClient(6379, '127.0.0.1', {auth_pass: 'password'});
// 设置Express的Session存储中间件
app.use(expressSession({store:new RedisStore({client: redisClient}), secret:'password', resave:false, saveUninitialized:false}));


2.4 Session的使用

配置完成后,express-session会在HTTP的请求对象request中添加一个session属性,通过这个属性我们可以实现Session会话的读写,而express-session会自动将其持外化到Redis存储中。

配置完成后,我们可以像下面这样读写Session

// 设置Session
req.session.site = {name:'IT笔录', domain:'itbilu.com'};

// 读取Session
var site = req.session.site;


在配置Session存储前,我们读取或设置Session时,会报类似下面的错误:

// 设置时
Cannot set property 'user' of undefined

// 读取时
Cannot read property 'user' of undefined