Django如何自动为接口添加Cognito认证 仅豁免指定接口
解决方案
报错根因说明
- 方案1中间件报错:DRF的
Response对象需要经过DRF的渲染流程处理才能返回,中间件直接返回Response时还没设置accepted_renderer属性,触发断言错误。 - 方案2自定义认证类报错:DRF的
BaseAuthentication子类的authenticate方法只允许返回(用户实例, 认证信息)的元组,或者抛出认证异常,不能直接返回Response对象,返回Response会导致DRF后续处理逻辑异常。
正确实现方案(DRF原生认证+权限体系,兼容所有视图类型)
步骤1:修正自定义Cognito认证类
authenticator.py代码如下:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from datetime import datetime from django.contrib.auth.models import AnonymousUser from cheers.core.api.jwt_helpers import decode_cognito_jwt class CognitoAuthentication(BaseAuthentication): def authenticate(self, request): auth = request.headers.get("Authorization", None) if not auth: raise AuthenticationFailed('Authorization header expected') parts = auth.split() if parts[0].lower() != "bearer": raise AuthenticationFailed('Authorization header must start with bearer') elif len(parts) == 1: raise AuthenticationFailed('Token not found') elif len(parts) > 2: raise AuthenticationFailed('Authorization header must be Bearer token') token = parts[1] try: res = decode_cognito_jwt(token) expiration = datetime.utcfromtimestamp(res['exp']) current_utc = datetime.utcnow() if current_utc > expiration: raise AuthenticationFailed(f'current time:{current_utc} is after expiration:{expiration}, Please login again') except Exception: raise AuthenticationFailed("Invalid JWT") # 认证通过返回用户和认证信息,可根据业务替换为实际用户实例 return AnonymousUser(), None
步骤2:实现豁免认证装饰器@donotauth
新建decorators.py:
def donotauth(view_func): """标记视图不需要认证""" view_func.donotauth = True return view_func
步骤3:实现配套权限类
新建permissions.py:
from rest_framework.permissions import BasePermission class IsAuthenticatedUnlessDonotAuth(BasePermission): def has_permission(self, request, view): # 视图如果被@donotauth标记,直接放行 if getattr(view, 'donotauth', False) or getattr(getattr(view, 'view_class', None), 'donotauth', False): return True # 否则检查是否通过认证 return request.user is not None
步骤4:全局配置DRF设置
修改settings.py:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'cheers.utils.authenticator.CognitoAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'cheers.utils.permissions.IsAuthenticatedUnlessDonotAuth', ), }
步骤5:使用示例
函数视图豁免认证:
@donotauth @api_view(['GET']) @swagger_auto_schema( operation_description="Get <count> most recent posts by category" ) def get_most_recent_posts_by_category(request, category, count): return Response(status=status.HTTP_200_OK)
类视图豁免所有方法认证:
from django.utils.decorators import method_decorator @method_decorator(donotauth, name='dispatch') class PublicView(APIView): def get(self, request): return Response()
类视图豁免单个方法认证:
class MixedView(APIView): @method_decorator(donotauth) def get(self, request): # 该方法无需认证 return Response() def post(self, request): # 该方法需要认证 return Response()
内容的提问来源于stack exchange,提问作者user12314098
相关产品推荐
相关产品推荐

