ExpressJS结合Redis存储Session时设置会话值报无效参数类型错误
问题根因
这个TypeError: Invalid Argument Type是版本兼容问题,和你往session里存什么内容没关系:
- 7.0以上版本的
connect-redis移除了默认内置的JSON序列化逻辑 - 4.0以上版本的
redis(node-redis客户端)只接受字符串、Buffer类型的写入参数,直接传入JS对象就会抛出类型错误
你之前用默认内存存储session的时候,express-session直接操作内存里的JS对象不需要序列化,切换到Redis之后没有显式配置序列化规则,就会触发这个报错。
修复步骤
- 首先修正connect-redis的引入方式(7.x版本适用,如果你用的是6.x及以下可以跳过这步)
把原来的const redisStore = require('connect-redis')(session);替换为:const RedisStore = require('connect-redis').default; - 给Redis存储实例显式配置序列化规则,修改session配置里的store字段:
store: new RedisStore({ client: redisClient, // 显式指定JSON序列化/反序列化规则 serializer: { parse: JSON.parse, stringify: JSON.stringify } }), - 修复Redis异步连接的时序问题:你现在的代码里
redisClient.connect()是异步执行,没有等连接成功就挂载session中间件,服务刚启动时的请求可能因为Redis未就绪触发异常。可以把中间件加载逻辑调整为等Redis连接就绪后再注册,同时补充连接错误监听避免服务崩溃:// 调整后完整的中间件代码 const session = require('express-session'); const {v4: uuidv4} = require('uuid'); const RedisStore = require('connect-redis').default; const redis = require('redis'); const redisClient = redis.createClient({ host: 'localhost', port: 6379 }); redisClient.on('error', err => console.error('Redis Client Error', err)); redisClient.connect().then(() => console.log('Redis connected!')); module.exports = async (app) => { // 等待Redis连接就绪再挂载中间件 await redisClient.ping(); app.use( session({ store: new RedisStore({ client: redisClient, serializer: { parse: JSON.parse, stringify: JSON.stringify } }), secret: [process.env.SIGN_SESSION, process.env.VALIDATE_SESSION], name: 'sessionId', genid: function(req) { return uuidv4(); }, saveUninitialized: false, resave: false, cookie: { httpOnly: true, sameSite: true, secure: process.env.ENV === 'prod', signed: true } }), ); console.log('Middleware loaded! (Session)'); };
注意事项
改完配置后不需要手动对存入session的对象做JSON序列化,直接按原来的写法req.session.user = userObj赋值即可,字符串、普通JS对象、数字等常规可序列化类型都可以正常存入。
内容的提问来源于stack exchange,提问作者darby
相关产品推荐
相关产品推荐

