0

我已经为基于令牌的身份验证实现了 simpleJWT。我创建了一个简单的 hello world 测试 API。

在测试时,我正在使用 /rest-auth/login/ 进行日志记录并用于生成使用 /api/token/ - 两者都可以正常工作。

现在进行测试,我使用用户 XYZ(拥有 helloworld api 的访问权限)登录并使用另一个用户 ABC(没有 helloworld api 的访问权限)生成令牌。

所以现在用户 XYZ 已通过身份验证(好的),但我有用户 ABC 的令牌(好的)。

现在,当我使用为使用 ABC 生成的令牌调用 API 时,即使用户 ABC 对 API 没有权限,我也可以访问 helloworld api!因为拥有权限的用户 XYZ 已经登录。

问题是当多个用户将使用该站点时,总是会出现这种情况。如何解决?下面还介绍了一些代码片段:

我的 settings.py 被剪断了

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',

    ),
}

代码基本上是一个为用户进行身份验证的装饰器如下

def user_is_ADM(fun_c):
    @wraps(fun_c)
    def wrapped(request, *args, **kwargs):
        # 1 = ADM
        if(request.user and request.user.is_authenticated) :   <--- here is the issue
            user_data = UserProfile.objects.get(user_id = request.user.id)

           # user profile as as a user type
            u = user_data.user_type
            if  u == 1:
                return fun_c(request, *args, **kwargs)
            else:
                raise PermissionDenied
    return wrapped

在这种情况下我的策略应该是什么?

编辑 如下修改了我的装饰器,它正在工作。如果我做错了什么,请有人评论

def user_is_ADM(fun_c):
    @wraps(fun_c)
    def wrapped(request, *args, **kwargs):
        juser = get_user(request)
        if juser.is_authenticated:
            user_jwt = JWTAuthentication().authenticate(Request(request))
            if user_jwt is not None:
                if request.user == user_jwt[0]:
                    k = user_jwt[0].userprofile.get_user_type_display()

                    if k == 'ADM':
                        return fun_c(request,*args,**kwargs)
                    else:
                        raise PermissionDenied
                else:
                    raise PermissionDenied
            else:
                raise PermissionDenied
        else:
            raise PermissionDenied
    return wrapped

4

1 回答 1

0

查看此文档https://www.django-rest-framework.org/api-guide/permissions/(自定义权限)

设置一般权限设置 (IsAuthenticated) 时。它确实是在对用户进行身份验证,但不随时验证他们的权限

class IsAuthenticated(BasePermission):
    """
    Allows access only to authenticated users.
    """

    def has_permission(self, request, view):
        return bool(request.user and request.user.is_authenticated)

如果基本的管理员和用户身份验证还不够。您可以实现自定义权限

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    """
    extracted from the documentation
    """
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view):
        """
        add authentication logic and return a boolean value
        """
        # ...
        # return bool()

在视图中

from rest_framework.views import APIView
from modulename.permissions import CustomerAccessPermission

class ExampleView(APIView):
    """
    ...
    """
    permission_classes = (CustomerAccessPermission,)

    def get(self, request, format=None):
        """
        ...
        """

这是一个具有 django 身份验证权限的示例

from typing import Tuple
from rest_framework.permissions import BasePermission

class CustomPermission(BasePermission):
    """
    ...
    """
    list_permissions: Tuple[str] = (
        'modelname.view_modelname',
        'modelname.add_modelname',
        'modelname.change_modelname',
        'modelname.delete_modelname',
    )

    def has_permission(self, request, view) -> bool:
        return bool(
            request.user.has_perms(self.list_permissions)
            or
            request.user and request.user.is_staff
            or
            request.user and request.user.is_superuser
        )

概括

关于一般的语法,你不会看到任何变化,你必须在视图中导入你的权限或装饰器,区别在于运行时和 django 评估权限的方式

请记住,装饰器只不过是 func(func()) 的一种概括方式。所以你应该总是评估视图并调用装饰器修改的方法

相反,此框架中的权限始终定义为权限类列表。在执行视图主体之前,会验证列表中的每个权限。如果任何权限验证失败,都会产生异常。权限被拒绝或异常。会产生未经验证的异常,视图主体不会被执行。(查阅文档以获得完整的解释)

您应该评估哪种方法最适合您的情况(性能、语法等)。

# you can set your permission in the general settings to avoid importing into each file
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'modulename.permissions.CustomPermission',
    ),
    # ...
}

于 2019-10-05T18:50:40.377 回答