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
相关产品推荐
相关产品推荐

