1

我默认使用带有 IsAuthenticatedOrTokenHasScope 权限的 drf 和 oauth 工具包。我有一个包含范围的视图 required_scopes = ['mod', 'admin']当用户登录应用程序时,他有特殊的组来定义他的权限范围。因此,当版主登录应用程序时,他会获得mod范围。当他调用我的视图时,他得到 403,因为allow_scopes在 AccessToken 模型中返回 False。那是因为resource_scopesis ['mod', 'admin'] 并且provided_scopes 是'mod'。当方法allow_scopes检查时resource_scopes.issubset(provided_scopes),她返回 False,这在我的情况下不是故意的。

是否有任何其他选项不覆盖 AccessToken 模型中的 allow_scopes 来定义此视图需要 scopemod或 scope admin。?

4

1 回答 1

1

我想我找到了一种方法来让它工作。oauth2_provider没有提供任何功能来实现这一点。所以,我所做的是我定义了自己的自定义权限,类似于TokenHasScope. 因此,创建一个名为permissions.py并粘贴代码的文件

from rest_framework import permissions 
from django.core.exceptions import ImproperlyConfigured
from rest_framework.exceptions import PermissionDenied
from oauth2_provider.settings import oauth2_settings

class TokenHasAtLeastOneScope(permissions.BasePermission):
    """
    The request is authenticated as a user and the token used has at least one of the right scope
    """

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

        if not token:
            return False

        if hasattr(token, "scope"):  # OAuth 2
            required_scopes = self.get_scopes(request, view)
            log.debug("Required scopes to access resource: {0}".format(required_scopes))

            # If any scope in the list of required_scopes is valid, return True.
            for given_scope in required_scopes:
                if token.is_valid([given_scope]):
                    return True


            # Provide information about required scope?
            include_required_scope = (
                oauth2_settings.ERROR_RESPONSE_WITH_SCOPES
                and required_scopes
                and not token.is_expired()
                and not token.allow_scopes(required_scopes)
            )

            if include_required_scope:
                self.message = {
                    "detail": PermissionDenied.default_detail,
                    "required_scopes": list(required_scopes),
                }

            return False

        assert False, (
            "TokenHasAtLeastOneScope requires the"
            "`oauth2_provider.rest_framework.OAuth2Authentication` authentication "
            "class to be used."
        )

然后在您看来,导入权限并进行相应设置

permission_classes = (permissions.TokenHasAtLeastOneScope)
required_scopes = ['mod', 'admin']

在上面的自定义TokenHasAtLeastOneScope中,代码类似于TokenHasScope. 唯一改变的行是

for given_scope in required_scopes:
    if token.is_valid([given_scope]):
        return True

哪个循环遍历required_scopes列表中的项目,如果找到有效范围,则返回 True。

于 2021-05-28T13:08:44.230 回答