只能登录一个用户
持久化session,保存每一个登录用户的session。解决方式是使用 redis
, express
框架配合 redis
相关的库可以非常方便地存储用户的session,如下配置 express-session
即可实现自动化地实现保存和删除session。
const session = require('express-session')
const redis = require('redis')
const RedisStore = require('connect-redis')(session)
let redisClient = redis.createClient()
// 开放 redist 实例到全局,可以封装后 export 导出
global.redisClient = redisClient
app.use(
session({
name: 'blog_cookie',
secret: 'secret key',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
},
store: new RedisStore({ client: redisClient }),
})
)
使用connect-redis
前是想通过官方的express-session使用介绍中找到多用户登录的方法。之前的情况是想通过一个全局变量来保存每次下发的session,可是发现session集成到express后只能通过请求参数来获取用户访问时携带过来的cookie信息,尽管通过查询获知配置参数store
可以告知session保存方式,可是这东西如果用数组或者set/map去保存,看起来似乎有点不可控,要是服务器挂了,那么所有用户的session就都没了。
于是在看到了官方这个文章最下面Seesion store Implementation的介绍推荐使用connect-redis
时,就跟随官方推荐使用了。根据后面的了解,redis的好处是数据库运行在内存中,对于session这种小量存储,且I/O密集的数据利用内存速度优势可以提升访问速度。
此时通过RedisStore
即可实现session的自动化存储了,来了一个用户,存到数据库中,用户退出了,自动从数据库中删除session对应的key:value
。
总结:解决思路是:session —> 多个session —> session持久化
多端不同用户登录,后登录的用户会影响到之前用户的主页信息展示
看起来已经完成多用户登录功能了,每个用户信息都实现了持久化存储,可是又由于此次是一个ssr
项目(Express+art-template),用户在界面上展示的信息通过一个全局对象req.app.locals
来保存,每次新的用户登录就会造成req.app.locals.user
数据的更新,从而使博客主页的用户名被固定为最后登录系统的用户名。
解决办法:
- 用户登录时将用户的信息跟随session一起保存到redis数据库中;
- 根据浏览器访问服务器时会随之携带cookie信息,通过
req.sessionID
(sessionID是express-session生成的唯一id,这个值还可以通过req.session.id
获取)对比数据库中的sessionID
,取出在数据库中对应sessionID的user信息,重新赋值到req.app.locals.user
中。
这样就可以保证每个用户来的时候服务器都提供正确的信息。
思路:
服务器不管来的人是谁(就像景区售票员,它只管卖票发票给客户,客户通过这个票据可以在规定时间范围内自由出入景区),只要你携带cookie,那么我就验证你的身份(通过对比数据库内的信息)。没有携带,只要可以合法登录,那就给浏览器发一个cookie。
项目中就是只要在页面内涉及使用req.app.locals.user
的,那么就一定要验证cookie,并重新设置req.app.locals.user
的值以保证服务器向用户提供服务时是唯一的。
最后,用了redis还是要稍微熟悉一下redis的,一开始完全不知道如何知道session是以什么样的方式保存到数据库中的,后来通过网络查询,知道在控制台中使用keys *
命令可以获取所有的key,然后看到了sess:xxxxxx
字样的key,再通过get 'sess:xxxxxx'
看到了保存的session值。一步步尝试获取到了数据库中的session,然后在代码中通过redis的get函数获取值与req.sessionID
做对比。