每个特定方法的 Django OAuthToolkit 范围

Django OAuthToolkit Scopes per specific method

我正在使用 Django Rest Framework 和 OAuthTookit

我希望令牌提供的范围应该是特定于 HTTP 方法的。例如:- 同一个 APIView 的 GET、PUT、DELETE 应该有不同的范围。

以下是我的 API。

class MyView(RetrieveUpdateDestroyAPIView):
    permission_classes = [TokenHasScope]
    required_scopes = ['scope1']
    serializer_class = ModelSerializer
    queryset = Model.objects.all()

目前,范围设置在class级别,这意味着访问所有的GET、PUT和DELETE方法,令牌应该有scope1

我希望不同的 HTTP 方法应该有不同的范围。如何为不同的方法设置不同的范围?

要处理这种情况,我认为您需要实施新权限 class,如下所示:

class TokenHasScopeForMethod(TokenHasScope):

     def has_permission(self, request, view):
         token = request.auth

         if not token:
             return False

         if hasattr(token, "scope"):
             # Get the scopes required for the current method from the view
             required_scopes = view.required_scopes_per_method[request.method]

             return token.is_valid(required_scopes)

然后像这样在您的视图中使用它:

class MyView(RetrieveUpdateDestroyAPIView):
     permission_classes = [TokenHasScopeForMethod]
     required_scopes_per_method = {'POST': ['post_scope'], 'GET': ['get_scope']}
     serializer_class = ModelSerializer
     queryset = Model.objects.all()

也许你可以使用TokenMatchesOASRequirements权限class

class SongView(views.APIView):
    authentication_classes = [OAuth2Authentication]
    permission_classes = [TokenMatchesOASRequirements]
    required_alternate_scopes = {
        "GET": [["read"]],
        "POST": [["create"], ["post", "widget"]],
        "PUT":  [["update"], ["put", "widget"]],
        "DELETE": [["delete"], ["scope2", "scope3"]],
    }

我喜欢@clément-denoix 的回答,但会稍微调整一下。

与其重新加载 TokenHasScope.has_permission 我建议重新定义 TokenHasScope.get_scopes 因为它是一种更小的方法,非常适合您的需要。原始 has_permission 方法还有我更愿意保留的附加逻辑。

像这样应该可以解决问题:

from django.core.exceptions import ImproperlyConfigured
from oauth2_provider.contrib.rest_framework import TokenHasScope


class TokenHasScopeForMethod(TokenHasScope):
    def get_scopes(self, request, view):

        try:
            scopes = getattr(view, "required_scopes_per_method")
            return scopes[request.method]
        except (AttributeError, KeyError):
            raise ImproperlyConfigured(
                "TokenHasScope requires the view to define the required_scopes_per_method attribute"
            )