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

如何判断Django admin登录状态并实现双端登录注销态双向同步

问题根源

你当前的登录状态依赖两套体系:

  • Django原生Session:给Admin后台登录使用
  • DRF Token:给落地页前端登录使用
    你自己实现的落地页登录逻辑同时完成了「生成Session」和「创建/获取Token」两个操作,所以从落地页登录后Admin可以直接用Session访问。但Django自带的Admin登录/注销逻辑只处理Session,不会处理Token,因此才会出现单向同步的问题。

解决方案

1. 实现登录双向同步

我们用Django内置的user_logged_in信号监听所有登录成功事件,不管是落地页还是Admin入口登录,都自动生成Token:

  1. 在你的App下新建signals.py,添加如下代码:
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

# 监听所有登录成功事件,自动生成Token
@receiver(user_logged_in)
def generate_token_after_login(sender, request, user, **kwargs):
    Token.objects.get_or_create(user=user)
  1. 注册信号,修改你App的apps.py:
from django.apps import AppConfig

class 你的App名Config(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = '你的App名'

    def ready(self):
        import 你的App名.signals
  1. 在settings.py的INSTALLED_APPS中,把你的App配置修改为上面的AppConfig:
INSTALLED_APPS = [
    # 替换原来的你的App名条目
    '你的App名.apps.你的App名Config',
    # 其他原有配置...
]
  1. 落地页前端同步登录状态:在落地页的首页接口/视图中,判断如果用户已经通过Session认证(即Admin登录过的状态),直接返回Token给前端存储即可:
# 落地页视图示例
def landing_index(request):
    token = ''
    if request.user.is_authenticated:
        token_obj, _ = Token.objects.get_or_create(user=request.user)
        token = token_obj.key
    # 模板渲染时把token传给前端,或者接口返回给前端存入localStorage
    return render(request, 'index.html', {'token': token})

2. 实现注销双向同步

同样用user_logged_out信号监听所有注销事件,注销时自动删除对应Token:

  1. 在之前的signals.py中追加注销信号处理逻辑:
# 监听所有注销成功事件,自动删除Token
@receiver(user_logged_out)
def delete_token_after_logout(sender, request, user, **kwargs):
    if user:
        Token.objects.filter(user=user).delete()
  1. 修复你现有注销接口的错误逻辑:你当前的注销代码不需要传入用户名密码,也不需要调用update_session_auth_hash(该方法仅用于修改密码后刷新Session,注销场景不需要),修改后代码如下:
@api_view(['POST'])
@authentication_classes((TokenAuthentication,))
@permission_classes((IsAuthenticated,))
def logout(request):
    try:
        # 调用auth.logout会自动触发user_logged_out信号,删除Token
        auth.logout(request)
        return Response({"status": STATUS['SUCCESS'], "message": MESSAGE_SUCCESS['LOGOUT']}, status=status.HTTP_200_OK)
    except:
        return Response({"status": STATUS['ERROR'], "message": MESSAGE_ERROR['LOGOUT']}, status=status.HTTP_200_OK)

3. 可选:前端本地存储同步

如果你的落地页前端把Token存在localStorage中,Admin注销后前端本地还会留存旧Token,可添加一个中间件处理这种场景:

# 新建middleware.py
from rest_framework.authtoken.models import Token
from django.http import JsonResponse

class SyncAuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        if auth_header.startswith('Token '):
            token_key = auth_header.split(' ')[1]
            token = Token.objects.filter(key=token_key).first()
            # Token存在但Session已失效,说明用户从Admin端注销
            if token and not request.user.is_authenticated:
                token.delete()
                return JsonResponse({"status": "error", "message": "登录已失效"}, status=401)
        return self.get_response(request)

把该中间件添加到settings.py的MIDDLEWARE列表中,放在django.contrib.sessions.middleware.SessionMiddleware之后即可。前端收到401状态码时自动清除本地存储的Token和登录状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:06:05