You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express.js中重定向后Cookie不持久的问题求助

问题描述

我正在实现Discord第三方认证功能(问题与Discord API无关),认证流程如下:

  1. 用户访问http://localhost:3000/auth
  2. 点击“Login with Discord”按钮,跳转至Discord登录界面
  3. 输入正确凭据后,Discord携带授权码跳转回应用
  4. 应用通过授权码换取access_token,用express-session初始化会话并存储discord_access_token
  5. 用户被重定向至仪表盘

异常情况:前4步均正常执行,但通过discordAuthController.js中的res.redirect('/dashboard')跳转后,开发者工具中无法看到会话Cookie,客户端无法获取会话数据;但手动访问/dashboard路由时,Cookie显示正常。测试发现只要使用res.redirect('/ROUTE')跳转,客户端存储中就不会出现Cookie,必须手动刷新或直接访问路由才会显示。


相关代码

routes/auth/discord.js

import express from 'express';
import session from 'express-session'

import * as discordAuthController from '../../app/controllers/auth/discordAuthController.js'

const router = express.Router()

router.get('/', async (req, res) => {
    await discordAuthController.index(req, res)
    .catch(err => {
        console.log(err)
        res.sendStatus(500)
    })
})

export default router

/controllers/auth/discordAuthController.js

import { exchangeToken } from '../../models/auth/discord.js'

async function index(req, res) {
  await exchangeToken(req.query.code)
  .then(response => {
    req.session.initialised = true
    req.session.discord_user_id = response.access_token

    res.redirect('/dashboard')
  })  
  .catch(err => {
    console.log(err)
    res.sendStatus(500)
  })
};

export { index }

/models/auth/discord.js

import * as dotenv from 'dotenv' 
dotenv.config()

const api_endpoint = process.env.DISCORD_API_ENDPOINT
const client_id = process.env.DISCORD_CLIENT_ID
const client_secret = process.env.DISCORD_CLIENT_SECRET
const redirect_uri = process.env.DISCORD_REDIRECT_URI
const guild_id = process.env.DISCORD_GUILD_ID

async function makeExchange(auth_code) {
    return await fetch(api_endpoint, {
        method: 'POST',
        headers: { 
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: new URLSearchParams({
          client_id,
          client_secret,
          grant_type: 'authorization_code',
          code: auth_code,
          redirect_uri
        })
      })
    .then(response => response.json())
}

export async function exchangeToken (auth_code) {
    return await makeExchange(auth_code)
}    

问题原因及解决方案

1. express-session全局配置缺失关键参数

你的路由文件仅导入了session但未在全局正确配置中间件,导致会话Cookie无法在重定向场景下正常传递。需在应用入口文件(如app.js/server.js)中全局配置express-session:

import session from 'express-session';

app.use(session({
  secret: process.env.SESSION_SECRET || 'your-random-secret-key',
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: process.env.NODE_ENV === 'production', // 生产环境开启HTTPS时设为true
    httpOnly: true,
    sameSite: 'lax', // 核心:允许跨站重定向携带Cookie,避免被浏览器拦截
    maxAge: 24 * 60 * 60 * 1000 // Cookie有效期,按需调整
  }
}));

注意:sameSite: 'lax'是解决重定向Cookie丢失的关键,若设为strict,跨站重定向(如从Discord跳转回应用)会被浏览器阻止Cookie发送。

2. 重定向前未等待会话持久化完成

express-session默认异步保存会话,直接调用res.redirect可能导致会话还未写入存储,重定向响应未携带Cookie。需手动调用req.session.save()确保会话保存后再重定向:

// 修改discordAuthController.js的index函数
async function index(req, res) {
  try {
    const response = await exchangeToken(req.query.code);
    req.session.initialised = true;
    req.session.discord_user_id = response.access_token;

    // 等待会话保存完成后再执行重定向
    req.session.save((err) => {
      if (err) {
        console.log(err);
        return res.sendStatus(500);
      }
      res.redirect('/dashboard');
    });
  } catch (err) {
    console.log(err);
    res.sendStatus(500);
  }
};

3. 路由文件重复导入session导致冲突

删除routes/auth/discord.js中的import session from 'express-session',确保仅全局配置一次session中间件,避免重复加载引发的配置冲突。


验证步骤

  1. 完成上述配置修改后重启服务
  2. 重新走Discord认证流程
  3. 跳转至/dashboard后,查看开发者工具的Cookie面板,确认会话Cookie已正常存在

内容的提问来源于stack exchange,提问作者felpsey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:05:16