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"
快速验证步骤
- 直接在浏览器地址栏访问
http://localhost:8000/auth/user(跳过前端),看是否能返回已认证用户信息 - 查看
django_session表,确认存在未过期的Session记录 - 在
get_authenticated_user中打印request.session.session_key,对比登录前后的Session Key是否一致
内容的提问来源于stack exchange,提问作者Le Bateleur
相关产品推荐
相关产品推荐

