GraphQL结合Redis实现cookie会话功能失效,附代码求解决方案
解决方案
按以下顺序修改你的代码即可修复cookie失效问题:
1. 修复Redis连接配置
你使用的是v4及以上版本的redis包,新版客户端创建后需要主动触发连接,否则session数据无法写入redis,修改index.ts中redis相关代码:
const redisClient = createClient(); // 新增以下两行代码 redisClient.connect().catch(console.error); redisClient.on("error", (err) => console.log("Redis Client Error", err));
2. 修复login接口逻辑
你的login方法没有从上下文中解构req对象,所以之前写入session的代码全部无效,同时不要手动修改系统自动生成的req.sessionID/req.session.id字段,正确写法:
// 修改login方法的参数解构,新增req async login( @Arg('username') username:string, @Arg('password') password:string, @Ctx() {em, req}: MyContext ): Promise<UserResponse> { // 原有用户名、密码验证逻辑保持不变 const valid = await argon2.verify(user.password, password); if (!valid) { return { errors: [ { field: "password", message: "incorrect password", } ] } } // 新增代码:将用户id写入session req.session.userId = user.id; return { user }; }
3. 修复me查询逻辑错误
你之前用req.sessionID匹配用户名的逻辑完全错误,sessionID是express-session自动生成的会话标识,和用户业务字段无关,修改为:
@Query (() => User, {nullable:true}) async me(@Ctx() { em, req}: MyContext) { // 判断session中是否存在userId if (!req.session.userId) return null; // 用session存储的userId查询对应用户 const user = await em.findOne(User, {id: req.session.userId}) return user; }
4. 适配本地开发的cookie配置
当前配置sameSite: "none"仅在secure: true时生效,开发环境__prod__为false,会导致浏览器拒绝存储cookie,修改配置:
cookie: { maxAge: 1000 * 60 * 60 * 24 * 365 * 10, httpOnly: true, sameSite: __prod__ ? "none" : "lax", // 生产环境用none,开发环境用lax secure: __prod__, },
5. 前端请求配置
- 若使用Apollo Studio测试,需要在设置中打开
Include credentials开关 - 若使用React前端发请求,需要给
ApolloClient配置credentials: "include"
可选:解决类型报错
如果Typescript提示req.session.userId不存在,需要在types.ts中扩展express的Session类型:
declare module 'express-session' { interface Session { userId: number; // 类型与你的用户id字段保持一致即可 } }
内容的提问来源于stack exchange,提问作者Morgade
相关产品推荐
相关产品推荐

