Django REST API如何实现全局登录校验避免每个接口重复代码
方案1:自定义DRF全局/局部认证类(最推荐,符合DRF设计规范)
DRF本身就支持自定义认证类,会在请求进入视图函数前自动执行校验逻辑,校验失败直接返回错误,完全不用在每个视图里写判断。
首先编写自定义认证类:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed class JWTLoginAuthentication(BaseAuthentication): def authenticate(self, request): # 将原有verify_login逻辑挪到此处 verify_response = verify_login(request) if verify_response is not None: # 抛出认证失败异常,DRF会自动转换为对应HTTP响应 raise AuthenticationFailed(detail=verify_response.data, code=verify_response.status_code) # 校验成功返回(用户对象, None),后续视图可直接通过request.user获取用户信息 return (request.user, None)
使用方式分两种:
- 全局生效:在
settings.py中配置REST_FRAMEWORK的默认认证类,所有接口默认走校验逻辑,无需单独配置视图
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ '你的模块路径.JWTLoginAuthentication', ] }
- 局部生效:仅给需要校验的视图添加,公开接口(比如登录、注册)无需配置,直接在视图类指定认证类属性即可
class PostView(APIView): authentication_classes = [JWTLoginAuthentication] # 后续post、get方法完全不需要编写校验代码,进入方法的请求均已校验通过 @swagger_auto_schema( request_body=PostSerializer, operation_description="Create a post object" ) def post(self, request): serializer = PostSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_description="Get all posts from the DB" ) def get(self, request): posts = Post.objects.all() serializer = PostSerializer(posts, many=True) return Response(serializer.data, status=status.HTTP_200_OK)
方案2:自定义装饰器(适合函数视图、仅部分方法需要校验的场景)
如果只有个别接口的个别方法需要登录校验,不想改动全局配置或整个视图的认证逻辑,可以用装饰器实现:
from functools import wraps def login_required(func): @wraps(func) def wrapper(view_instance, request, *args, **kwargs): verify_response = verify_login(request) if verify_response is not None: return verify_response return func(view_instance, request, *args, **kwargs) return wrapper
使用时直接给需要校验的方法加装饰器即可:
class PostView(APIView): @swagger_auto_schema( request_body=PostSerializer, operation_description="Create a post object" ) @login_required def post(self, request): # 无需额外编写校验逻辑 serializer = PostSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
方案3:重写父类APIView的dispatch方法
你之前考虑的继承父类方案也可以实现,只要重写请求分发的入口方法dispatch即可,不需要每个方法单独调用父类逻辑:
class BaseAuthAPIView(APIView): def dispatch(self, request, *args, **kwargs): # dispatch是所有请求进入视图方法的统一入口,在此处提前做校验 verify_response = verify_login(request) if verify_response is not None: return verify_response # 校验通过后再执行原生请求分发逻辑,进入对应get/post方法 return super().dispatch(request, *args, **kwargs)
使用时所有需要登录校验的视图直接继承BaseAuthAPIView即可,无需编写任何校验代码:
class PostView(BaseAuthAPIView): # 后续业务方法无需额外处理校验 def post(self, request): # 业务逻辑 ...
以上三种方案均符合DRY原则,无需重复编写校验代码,优先推荐方案1,是DRF原生支持的标准用法,适配性最高,也方便后续扩展权限校验等能力。
内容的提问来源于stack exchange,提问作者user12314098
相关产品推荐
相关产品推荐

