Discord OAuth白名单系统故障求助:Node.js角色验证逻辑修复
Discord白名单验证系统修复方案
核心问题梳理
- OAuth授权类型不匹配:登录链接使用
response_type=token,但后端采用授权码模式,需改为response_type=code - 令牌使用错误:调用服务器列表接口时误用授权码(code)作为身份凭证,应使用获取到的
accessToken - 权限不足:仅
identify权限无法获取用户角色,需新增guilds.members.read权限 - 接口数据误用:
/users/@me/guilds不返回用户角色,需调用服务器成员接口单独查询 - 逻辑分支缺失:未处理用户不在目标服务器的场景,也未按要求返回指定状态文本
修复后的完整代码
const express = require('express'); const axios = require('axios'); const app = express(); const PORT = 3000; const CLIENT_ID = '1332081657993367582'; const REQUIRED_ROLE_ID = "1325501603201028171"; const GUILD_ID = "1325501050471448647"; const CLIENT_SECRET = process.env.CLIENT_SECRET; const REDIRECT_URI = `https://dour-repeated-gasoline.glitch.me/validate`; const SCOPE = 'identify guilds.members.read'; app.get('/login', (req, res) => { const discordOAuthURL = `https://discord.com/oauth2/authorize?` + `client_id=${CLIENT_ID}` + `&response_type=code` + `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` + `&scope=${encodeURIComponent(SCOPE)}`; res.redirect(discordOAuthURL); }); app.get('/validate', async (req, res) => { const { code } = req.query; if (!code) { return res.status(400).send('ERROR'); } try { // 获取访问令牌 const tokenResponse = await axios.post('https://discord.com/api/oauth2/token', null, { params: { client_id: CLIENT_ID, client_secret: CLIENT_SECRET, grant_type: 'authorization_code', code, redirect_uri: REDIRECT_URI, }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, }); const accessToken = tokenResponse.data.access_token; const userId = tokenResponse.data.user_id; // 查询用户在指定服务器的成员信息 try { const memberResponse = await axios.get(`https://discord.com/api/v10/guilds/${GUILD_ID}/members/${userId}`, { headers: { Authorization: `Bearer ${accessToken}` }, }); // 检查是否拥有指定角色 const hasRequiredRole = memberResponse.data.roles.includes(REQUIRED_ROLE_ID); res.send(hasRequiredRole ? "ACCEPTED" : "DECLINED"); } catch (memberError) { // 404表示用户不在该服务器 if (memberError.response?.status === 404) { res.send("NONMEMBER"); } else { throw memberError; } } } catch (error) { console.error('Error during validation:', error.response?.data || error.message); res.status(500).send('ERROR'); } }); app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); });
关键修改说明
- OAuth流程修正:将登录链接的
response_type改为code,匹配后端授权码模式 - 权限补充:新增
guilds.members.read权限,允许查询用户在服务器的角色信息 - 令牌修正:调用接口时使用
accessToken而非授权码作为Bearer凭证 - 角色查询逻辑:通过
/guilds/{GUILD_ID}/members/{userId}接口获取用户在目标服务器的角色列表 - 状态返回完善:新增用户不在服务器的
NONMEMBER分支,异常统一返回ERROR - 错误处理优化:捕获成员查询的404错误,精准判断用户是否为服务器成员
内容的提问来源于stack exchange,提问作者İlyax
相关产品推荐
相关产品推荐

