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

如何允许非活跃用户登录并通过/user/端点实现自助账号激活

嘿,你已经搞定了非活跃用户登录和JWT获取的核心部分,剩下的就是精准控制权限啦!咱们来一步步解决这个问题:

问题根源

你遇到的/user/端点报错,是因为默认的IsAuthenticated权限类(或者rest-auth自带的用户详情视图)会隐性检查用户是否活跃——哪怕你已经让他们登录拿到了JWT。咱们需要给这个特定端点开个“后门”,同时把其他认证端点的权限锁死。

解决方案步骤

1. 自定义权限类,实现“仅允许非活跃用户访问自己的详情页”

在你的app里新建permissions.py,写一个针对性的权限类:

from rest_framework.permissions import IsAuthenticated
from rest_auth.views import UserDetailsView

class AllowInactiveSelfActivation(IsAuthenticated):
    def has_permission(self, request, view):
        # 先确保用户已通过JWT认证
        is_authenticated = super().has_permission(request, view)
        if not is_authenticated:
            return False
        
        # 核心规则:只有访问的是用户详情页,且是访问自己的账号时,允许非活跃用户
        if isinstance(view, UserDetailsView) and request.user == view.get_object():
            return True
        
        # 其他所有认证端点,必须是活跃用户才能访问
        return request.user.is_active

2. 替换rest-auth的默认用户详情视图

rest-auth自带的UserDetailsView用的是默认权限,咱们需要继承它并替换权限类。在你的app的views.py里:

from rest_auth.views import UserDetailsView
from .permissions import AllowInactiveSelfActivation

class CustomUserDetailsView(UserDetailsView):
    permission_classes = [AllowInactiveSelfActivation]

然后在urls.py里把原来的rest-auth用户路由替换成咱们自定义的视图:

from django.urls import path
from .views import CustomUserDetailsView

urlpatterns = [
    # 替换原rest-auth的/user/路由
    path('user/', CustomUserDetailsView.as_view(), name='rest_user_details'),
    # 其他你的自定义认证端点,保持用默认的IsAuthenticated权限
    path('my-custom-endpoint/', MyCustomAuthenticatedView.as_view(), name='custom_endpoint'),
]

3. 加固UserDetailSerializer的逻辑(可选但推荐)

为了防止用户恶意修改其他字段或者误操作,在你的自定义UserDetailSerializer里可以加个校验,确保用户只能修改is_active字段来激活自己:

from rest_framework import serializers
from django.contrib.auth import get_user_model

User = get_user_model()

class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'is_active')  # 你的字段列表
        read_only_fields = ('id', 'username', 'email')  # 把不需要修改的字段设为只读

    def update(self, instance, validated_data):
        # 只允许用户将自己的is_active从False改为True(激活)
        if 'is_active' in validated_data:
            if not instance.is_active and validated_data['is_active'] is True:
                instance.is_active = True
                instance.save()
            # 如果用户想停用自己,直接报错拦截
            elif validated_data['is_active'] is False:
                raise serializers.ValidationError({"detail": "You cannot deactivate your own account."})
        return instance

效果验证

  • 非活跃用户登录后,访问/user/可以正常获取自己的信息,并且能通过PUT请求修改is_active为true来激活账号;
  • 非活跃用户访问其他需要认证的自定义端点时,会返回403 Forbidden;
  • 活跃用户可以正常访问所有认证端点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:49:52