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

Django Rest Framework TokenAuthentication登出失效问题解决

Django Rest Framework TokenAuthentication 登出失效问题

我在使用DRF的TokenAuthentication时,访问http://192.168.1.67:8000/api/categories/需要登录认证,但点击登出按钮后操作未生效。终端显示触发登出时发起了两个请求:

[18/May/2023 10:42:14] "GET /api-auth/logout/?next=/api/categories/ HTTP/1.1" 302 0
[18/May/2023 10:42:15] "GET /api/categories/ HTTP/1.1" 200 32866

相关代码

urls.py

urlpatterns = [
    path('create/', views.CreateUserView.as_view(), name='create'),
    path('logout/',views.LogoutView.as_view(), name='logout'),    
    path('token/', views.CreateTokenView.as_view(), name='token'),
    path('me/', views. ManageUserView.as_view(), name='me'),    
    path('login/', obtain_auth_token, name='login' )
]

settings.py

LOGOUT_REDIRECT_URL = "/"
ACCOUNT_LOGOUT_REDIRECT_URL = "/"


REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_SCHEMA_CLASS':'drf_spectacular.openapi.AutoSchema',
    
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'SWAGGER_SETTINGS' : {
    'LOGIN_URL': 'rest_framework:login',
    'LOGOUT_URL': 'rest_framework:logout'
}    
}

views.py

class AnimalViewSet(viewsets.ModelViewSet):
    """
    该API端点用于查看动物描述。

    - 查看特定动物,在URL后附加[/id](/api/animal/1/)。
    - 查看某分类下的所有动物,使用[/category/id](/api/categories/1/)。
    """
    queryset = Animal.objects.all().order_by('name')
    serializer_class = AnimalSerializer
    permission_classes = ( IsAuthenticated, )


class CategoryViewSet(viewsets.ModelViewSet):
    """
    该API端点用于查看动物分类。

    所有分类包含其直接子分类和动物。

    - 查看特定分类,在URL后附加[/id](/api/categories/1/)。
    - 获取所有顶级分类使用[/main_groups](/api/categories/main_groups)。
    """

    def get_serializer_class(self):
        if hasattr(self, 'action') and self.action == 'main_groups':
            return MainGroupSerializer
        return CategorySerializer
    

    queryset = Category.objects.all().order_by('name')
    queryset = CategorySerializer.eager_load(queryset)
    serializer_class = get_serializer_class(super)
    permission_classes = (IsAuthenticated, )

解决方法

问题核心:默认的LogoutView仅清除Session会话,不会删除DRF的Token令牌,导致用户仍可通过Token访问接口。

1. 自定义登出视图,删除用户Token

修改views.py,添加自定义LogoutView来删除当前用户的AuthToken:

from rest_framework.authtoken.models import Token
from django.contrib.auth import logout
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class LogoutView(APIView):
    def post(self, request):
        # 删除当前用户关联的Token
        Token.objects.filter(user=request.user).delete()
        # 清除Session会话
        logout(request)
        return Response({"detail": "登出成功"}, status=status.HTTP_200_OK)

2. 修正URL配置

确保登出接口使用POST方法(GET方法不安全且不符合REST规范),urls.py保持原有配置即可,确保指向自定义的视图。

3. 调整前端登出请求方式

前端点击登出按钮时,需发送POST请求到/logout/接口。如果使用Swagger,需确保SWAGGER_SETTINGS中的LOGOUT_URL指向自定义的POST接口,或调整Swagger按钮的请求行为为POST。

4. 可选:优化认证配置(按需调整)

如果API仅使用Token认证,可在settings.py中调整认证类顺序或移除SessionAuthentication:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        # 不需要的话可注释以下两行
        # 'rest_framework.authentication.BasicAuthentication',
        # 'rest_framework.authentication.SessionAuthentication',
    ],
    # 其他配置不变
}

验证效果

修改完成后,触发登出会看到类似日志:

[18/May/2023 XX:XX:XX] "POST /logout/ HTTP/1.1" 200 XX

此时再访问/api/categories/会返回401未认证,说明登出生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:25:00