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

Django集成Discord OAuth2认证遇无限循环及匿名用户问题求助

解决Django Discord OAuth2认证后无限循环的思路

核心问题定位

从现象看,discord_login_redirect中调用login(request, user)后日志显示用户已认证,但跳转至/auth/user后又变回AnonymousUser,本质是Session未在后续请求中正确关联用户,导致@login_required触发重定向循环。

以下是针对性的排查与解决方向:

1. 修复自定义认证后端的关键实现

你的DiscordAuthenticationBackend必须确保两个核心方法正确实现,这是用户身份在请求间传递的核心:

  • authenticate必须返回**is_active=True的Django User实例**
  • get_user要能通过用户ID准确获取到用户对象

示例正确实现:

from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.models import User
from .models import DiscordUser

class DiscordAuthenticationBackend(BaseBackend):
    def authenticate(self, request, user_data=None):
        discord_id = user_data['id']
        # 查找或创建Discord关联用户
        discord_user, created = DiscordUser.objects.get_or_create(discord_id=discord_id)
        if created:
            # 生成Django User实例,默认is_active为True
            user = User.objects.create_user(username=f"discord_{discord_id}")
            discord_user.user = user
            discord_user.save()
        return discord_user.user  # 必须返回Django User实例

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

如果get_user返回None,Django会直接将用户判定为匿名,这是此类问题最常见的原因。

2. 修正Session与Cookie配置

  • ALLOWED_HOSTS必须包含当前域名:空列表会导致Django拒绝设置Session Cookie,修改为:
    ALLOWED_HOSTS = ["localhost", "127.0.0.1"]
    
  • 调整Session Cookie跨域参数:如果前端与后端跨域,需确保:
    # 本地开发无需设置SESSION_COOKIE_DOMAIN,或设为".localhost"适配子域
    SESSION_COOKIE_SAMESITE = "Lax"  # 跨域场景避免设为Strict,否则Cookie不随跳转发送
    SESSION_COOKIE_SECURE = False  # 本地HTTP开发必须设为False,否则浏览器不会保存Cookie
    SESSION_COOKIE_HTTPONLY = True  # 保持默认即可,防止前端XSS窃取Cookie
    
  • 强制保存Session:在login(request, user)后手动调用request.session.save(),确保Session数据被持久化:
    login(request, user)
    request.session.save()  # 新增该行,避免Session未及时写入数据库
    return redirect('/auth/user')
    

3. 验证前端跨域请求配置

如果/auth/user是通过前端AJAX请求访问的,必须确保请求携带Credentials:

  • Axios示例:
    axios.get('/auth/user', { withCredentials: true })
    
  • Fetch示例:
    fetch('/auth/user', { credentials: 'include' })
    

否则浏览器会自动忽略Session Cookie,后端自然识别不到已认证用户。

4. 检查中间件顺序与干扰项

你的中间件顺序基本合规,但需确认:

  • SessionMiddleware始终在AuthenticationMiddleware之前(已满足)
  • SocialAuthExceptionMiddleware放在AuthenticationMiddleware之后(已满足)
  • 没有自定义中间件意外重置request.user或清空Session数据

5. 修正Social Django配置拼写错误

你的settings里存在明显拼写错误:SOCIAL_AUTH_DN_REDIRECT_URI应为SOCIAL_AUTH_DISCORD_REDIRECT_URI,即使你自定义了回调视图,错误配置也可能引发内部逻辑异常,修正为:

SOCIAL_AUTH_DISCORD_REDIRECT_URI = "http://localhost:8000/oauth2/login/redirect"

快速验证步骤

  1. 直接在浏览器地址栏访问http://localhost:8000/auth/user(跳过前端),看是否能返回已认证用户信息
  2. 查看django_session表,确认存在未过期的Session记录
  3. 在get_authenticated_user中打印request.session.session_key,对比登录前后的Session Key是否一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:12:05