首页 > 解决方案 > 如何在 django rest 框架中传递多个 authentication_classes?

问题描述

我想创建一个可以使用 client_id 和 client_secret 以及访问令牌访问的 api。要使用 client_id 和 client_secret 访问 api,我有一个自定义身份验证类,如下所示:-

class ClientAuthentication(authentication.BaseAuthentication):
    @staticmethod
    def get_client_credentials(request):
        try:
            client_id = request.headers.get('CLIENTID')
            client_secret = request.headers.get('CLIENTSECRET')
        except:
            raise AuthenticationFailed
        return {
            'client_id': client_id,
            'client_secret': client_secret
        }

    def authenticate(self, request):
        credentials = self.get_client_credentials(request)

        client_instance = Application.objects.filter(
            client_id=credentials['client_id'],
            client_secret=credentials['client_secret'],
        ).first()

        if not client_instance:
            raise AuthenticationFailed
        return client_instance, None

    def get_user_application(self, request):
        credentials = self.get_client_credentials(request)

        application_instance = Application.objects.filter(
            client_id=credentials['client_id'],
            client_secret=credentials['client_secret'],
        ).first()

        if not application_instance:
            raise AuthenticationFailed
        return application_instance, None

我想使用的另一个身份验证类是默认的 OAuth2Authentication 我尝试将视图集的 authentication_classes 传递为:

authentication_classes = [ClientAuthentication | OAuth2Authentication]

但这给了我一个错误。我怎样才能做到这一点?

标签: djangoauthenticationdjango-rest-framework

解决方案


您应该通过 authenticate_header 区分身份验证器。当一个 AuthenticationClass(在 authenticate 方法中)读取一个不正确的 authenticate_header 时,应该返回 None,所以请求继续到下一个 Authenticator。例如,在 TokenAuthentication

def authenticate(self, request):
    auth = get_authorization_header(request).split()

    if not auth or auth[0].lower() != self.keyword.lower().encode():
        return None
    ...

如果您不返回 None,则身份验证将引发 APIException,因此不会调用下一个身份验证类。

此外,如果您想使用多个身份验证类,则必须在设置中定义它们,如文档中所示:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

或者在视图中定义它们。


推荐阅读