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

Django应用用户认证环节及限制多登录时is_authenticated恒为False问题

1. Django用户身份认证完成的环节

Django的用户身份认证逻辑由django.contrib.auth.middleware.AuthenticationMiddleware完成,该中间件会在请求处理阶段,从已解析的session中取出已登录用户的ID,查询对应的用户实例并赋值给request.user属性。因此要获取到已认证的request.user,自定义中间件必须放在AuthenticationMiddleware的执行顺序之后,你当前的中间件配置顺序是符合要求的。

2. 问题原因与调整方案

你遇到request.user.is_authenticated始终为False,还有逻辑本身的缺陷,主要有以下几个原因:

  • 你当前的逻辑是在请求处理阶段校验session,但用户首次登录时,auth.login()方法执行完成前request.user还是匿名用户,auth.login()执行后才会生成session_key、给request.user赋值为已认证用户,此时请求阶段的中间件已经执行完毕,首次登录时你无法存储对应的session_key
  • 代码本身存在语法问题:__str__方法、if user.session_key:行的缩进错误,filter查询不到结果会返回None不会抛异常,不需要用try-except包裹
  • 未对登录接口做白名单过滤,会导致登录请求本身直接被拦截

调整后的实现逻辑

第一步:新增登录/登出信号监听器

在你的应用models.py末尾新增如下代码,登录成功后直接写入session_key,避免中间件请求阶段拿不到刚登录的用户信息:

from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver

@receiver(user_logged_in)
def handle_user_login(sender, request, user, **kwargs):
    # 登录成功后直接更新session_key
    LoggedInUser.objects.update_or_create(
        user=user,
        defaults={"session_key": request.session.session_key}
    )

@receiver(user_logged_out)
def handle_user_logout(sender, request, user, **kwargs):
    # 登出后清空session_key
    LoggedInUser.objects.filter(user=user).update(session_key=None)

第二步:调整中间件逻辑

from django.http import JsonResponse

def MySessionMiddleware(get_response):
    def my_function(request):
        # 登录接口加白名单,避免拦截正常登录请求
        if request.path == "/替换为你的实际登录接口路径/":
            return get_response(request)
        if request.user.is_authenticated:
            user_session = LoggedInUser.objects.filter(user=request.user).first()
            if user_session and user_session.session_key:
                if user_session.session_key != request.session.session_key:
                    return JsonResponse(
                        "you already have a active session kindly logout from that", 
                        status=400, 
                        safe=False
                    )
        response = get_response(request)
        return response
    return my_function

额外注意点

如果使用Django默认的auth登录视图,白名单路径替换为/accounts/login/即可;可定期清理Django session表中已过期的session,同步删除对应LoggedInUser的无效session_key记录,避免误拦截。

内容的提问来源于stack exchange,提问作者Dhruv Singhal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 18:45:04