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

如何在Django REST Framework中配置多认证类实现API双访问方式?

解决DRF中同时支持两种认证方式的问题

你遇到的问题是因为DRF的authentication_classes需要接收一个认证类的列表/元组,而不是用|符号进行位运算操作——这个符号在Python里是按位或,完全不适合用来组合认证类。下面是具体的解决方法:

1. 正确配置视图集的认证类列表

直接把你的两个认证类放进列表里,DRF会按顺序尝试每个认证类,只要其中一个认证成功,就会使用该认证结果;如果所有认证都失败,才会返回401未认证。

示例代码:

from rest_framework.viewsets import ModelViewSet
from rest_framework.authentication import OAuth2Authentication
from .path_to_your_auth import ClientAuthentication  # 导入你的自定义认证类

class YourTargetViewSet(ModelViewSet):
    # 按你期望的优先级排序,这里先试Client认证,再试OAuth2
    authentication_classes = [ClientAuthentication, OAuth2Authentication]
    
    # 其他视图集配置
    # serializer_class = YourSerializer
    # queryset = YourModel.objects.all()

2. 调整自定义认证类的逻辑(关键)

你当前的ClientAuthentication在认证失败时直接抛出AuthenticationFailed异常,这会导致DRF立即终止认证流程,不会尝试后续的OAuth2Authentication。如果希望两种认证方式都能被尝试,需要修改authenticate方法,在认证不通过时返回None,而不是抛出异常。

修改后的自定义认证类:

from rest_framework import authentication, exceptions
from .models import Application

class ClientAuthentication(authentication.BaseAuthentication):
    @staticmethod
    def get_client_credentials(request):
        # 不需要try-except,headers.get()不会抛出异常,只会返回None
        client_id = request.headers.get('CLIENTID')
        client_secret = request.headers.get('CLIENTSECRET')
        return {
            'client_id': client_id,
            'client_secret': client_secret
        }
    
    def authenticate(self, request):
        credentials = self.get_client_credentials(request)
        
        # 如果没有提供client_id或client_secret,直接返回None,让DRF尝试下一个认证
        if not credentials['client_id'] or not credentials['client_secret']:
            return None
        
        client_instance = Application.objects.filter(
            client_id=credentials['client_id'],
            client_secret=credentials['client_secret'],
        ).first()
        
        # 凭证无效时返回None,继续尝试后续认证
        if not client_instance:
            return None
        
        # 认证成功,返回(认证主体, None),这里用client_instance作为认证后的主体
        return (client_instance, None)
    
    # 注意:get_user_application不是DRF认证类的标准方法,如果没有特殊需求可以删除
    # 保留的话也不会影响认证流程,但建议只保留DRF规范的方法

3. 验证逻辑

现在当请求进来时:

  • 如果请求头带有有效的CLIENTID和CLIENTSECRET,ClientAuthentication会认证成功,请求正常处理;
  • 如果Client认证失败(比如凭证无效或未提供),DRF会自动尝试OAuth2Authentication,如果请求带有有效的access token,就能通过认证;
  • 如果两种认证都失败,才会返回401 Unauthorized。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:02:42