使用Discord API实现「Login with Discord」(OAuth)时请求资源被拒绝的问题求助
解决Discord OAuth前端请求API的CORS问题
看起来你遇到的是**浏览器跨域资源共享(CORS)**限制的问题,同时还有几个需要注意的安全和权限细节,我来一步步帮你解决:
为什么会出现"Not allowed to request source"错误?
Discord的API(尤其是/guilds/{guild_id}/members/{user_id}这类接口)并不支持前端直接发起跨域请求——浏览器会因为CORS策略阻止这种请求,而且直接在前端暴露access_token是非常不安全的,恶意用户可以拿到这个token去操作你的账号权限。
正确的解决方案:通过后端代理请求
你需要搭建一个简单的后端服务,由后端来调用Discord的API,前端只和自己的后端交互,这样既避开CORS限制,又能保护access_token不泄露。
步骤1:确认OAuth授权范围
首先,你在发起Discord OAuth授权请求时,必须包含对应的权限范围:
- 要获取用户基本信息:
identify - 要获取用户在公会中的角色:
guilds.members.read
确保你的授权URL里包含这些scope参数,比如:
https://discord.com/api/oauth2/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=token&scope=identify%20guilds.members.read
步骤2:搭建后端代理(示例用Node.js/Express)
创建一个简单的后端接口,接收前端传来的access_token和token_type,然后由后端去调用Discord API:
const express = require('express'); const fetch = require('node-fetch'); const app = express(); const cors = require('cors'); app.use(cors()); app.use(express.json()); app.post('/discord-guild-member', async (req, res) => { const { accessToken, tokenType, guildId, userId } = req.body; try { const response = await fetch(`https://discord.com/api/guilds/${guildId}/members/${userId}`, { headers: { Authorization: `${tokenType} ${accessToken}` } }); const data = await response.json(); res.json(data); } catch (error) { res.status(500).json({ error: error.message }); } }); app.listen(3000, () => console.log('Backend running on port 3000'));
步骤3:修改前端代码,调用自己的后端接口
现在前端不再直接请求Discord API,而是请求你的后端:
window.onload = () => { const fragment = new URLSearchParams(window.location.hash.slice(1)); const accessToken = fragment.get('access_token'); const tokenType = fragment.get('token_type'); // 先获取用户自己的ID(从/users/@me接口) fetch('https://discord.com/api/users/@me', { headers: { authorization: `${tokenType} ${accessToken}`, }, }) .then(result => result.json()) .then(user => { const userId = user.id; const guildId = '874613987487121408'; // 你的公会ID // 调用后端代理接口 fetch('http://localhost:3000/discord-guild-member', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accessToken, tokenType, guildId, userId }) }) .then(result => result.json()) .then(response => { const username = response.user.username; const roles = response.roles.join(', '); document.getElementById('info').innerText = `用户名: ${username}\n角色ID列表: ${roles}`; }) .catch(console.error); }) .catch(console.error); };
额外注意事项
- 不要在前端硬编码固定的用户ID,应该先通过
/users/@me接口获取当前授权用户的ID,再去查询公会成员信息。 - 后端部署时,要确保你的域名是安全的(HTTPS),避免token在传输过程中被窃取。
- 如果你的应用需要处理多个用户,记得在后端做好token的验证和过期处理。
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

