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

Node.js实现Discord OAuth2登录系统问题:未登录却显示已登录

解决Discord OAuth2登录状态判断异常问题

你的代码核心问题是缺少会话状态管理机制:既没有在登录成功后持久化用户的登录状态,也没有在首页路由中检查该状态,导致无法区分用户是否已登录。以下是修复后的完整实现:

第一步:安装依赖

先补充安装会话管理所需的包:

npm install express-session

修复后的完整代码

const express = require("express")
const fetch = require('node-fetch')
const { URLSearchParams } = require('url')
const session = require('express-session') // 引入会话中间件
const app = express()

var config = {
  "clientId": process.env["CLIENT_ID"],
  "clientSecret": process.env['CLIENT_SECRET'],
  "redirectUri": "http://your-domain.com/authorize", // 替换为你的实际回调地址
  "discordAuthUrl": `https://discord.com/api/oauth2/authorize?client_id=${process.env["CLIENT_ID"]}&redirect_uri=${encodeURIComponent("http://your-domain.com/authorize")}&response_type=code&scope=identify` // 构造完整的授权链接
}

// 配置会话中间件,用于存储用户登录状态
app.use(session({
  secret: 'your-random-secret-key', // 替换为随机的密钥,用于加密会话
  resave: false,
  saveUninitialized: false,
  cookie: { secure: false } // 生产环境请设为true(需HTTPS)
}))

app.get("/", (request, response) => {
  // 检查会话中是否存在用户信息,判断登录状态
  if (request.session.user) {
    response.send(`已登录,欢迎你:${request.session.user.username}`)
  } else {
    response.send(`登录 with discord: <a href='${config.discordAuthUrl}'>login</a>`)
  }
})

app.get("/authorize", async (request, response) => {
  const code = request.query["code"]
  if (!code) {
    return response.send("授权失败:未获取到授权码")
  }

  try {
    // 交换授权码获取访问令牌
    const params = new URLSearchParams()
    params.append("client_id", config["clientId"])
    params.append("client_secret", config["clientSecret"])
    params.append("grant_type", "authorization_code")
    params.append("code", code)
    params.append("redirect_uri", config["redirectUri"])

    const tokenRes = await fetch(`https://discord.com/api/oauth2/token`, {
      method: "POST",
      body: params,
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
    })

    if (!tokenRes.ok) {
      throw new Error('令牌获取失败')
    }

    const tokenData = await tokenRes.json()
    // 使用访问令牌获取用户信息
    const userRes = await fetch('https://discord.com/api/users/@me', {
      headers: { Authorization: `Bearer ${tokenData.access_token}` }
    })

    if (!userRes.ok) {
      throw new Error('用户信息获取失败')
    }

    const userData = await userRes.json()
    // 将用户信息存入会话,标记登录状态
    request.session.user = {
      id: userData.id,
      username: userData.username,
      avatar: userData.avatar
    }

    response.redirect('/') // 登录成功后跳回首页
  } catch (err) {
    response.send(`登录失败:${err.message}`)
  }
})

app.listen(80, () => {
  console.log("Listening on :80")
})

关键修复点说明

  • 会话管理:通过express-session将用户登录状态存储在服务器端会话中,首页路由通过request.session.user判断是否已登录
  • 完整授权流程:补充了从授权码到访问令牌,再到获取用户信息的完整流程,确保登录状态与实际用户绑定
  • 错误处理:增加了授权码缺失、令牌获取失败、用户信息获取失败等场景的错误提示
  • 动态页面内容:首页根据登录状态动态显示登录链接或已登录欢迎信息

内容的提问来源于stack exchange,提问作者naj kanál

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:45:35