【问题标题】:RBAC with Django REST Framework带有 Django REST 框架的 RBAC
【发布时间】:2019-05-01 16:20:59
【问题描述】:

关于我应该使用什么来集成 RBAC 和 DRF 有什么建议吗?我已经看过 django-rest-framework-roles 和 django-guardian 但看起来都不太有希望。您的反馈将不胜感激。提前致谢。

【问题讨论】:

标签: django rest authorization rbac abac


【解决方案1】:

我所做的是为UsersGroupsPermissions 创建端点,并将DjangoModelPermissionsTokenAuthentication 结合使用。

您可以将User 模型覆盖为abstractUser,也可以按原样使用它。

UsersPermissionsGroup 创建序列化程序。

我个人遵循这种方法:

rbac/api/viewsets.py

from rest_framework import serializers
from customuser.models import CustomUser
from django.contrib.auth.models import Group, Permission

from rest_framework.authtoken.models import Token

class CustomUserSerializer(serializers.ModelSerializer):
    """ Custom User for authentication """
    class Meta:
        model = CustomUser
        read_only_fields = ["is_superuser"]
        fields = [
        "id",
        "is_superuser",
        "username",
        "first_name",
        "last_name",
        "email",
        "password",
        "is_staff",
        "is_active",
        "date_joined",
        "last_login",
        "is_admin",
        "is_insurer",
        "groups",
        ]

    # hash password
    def create(self, validated_data):
        user = super(CustomUserSerializer, self).create(validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user

class PermissionSerializer(serializers.ModelSerializer):
    """ Add permissions serializer """
    class Meta:
        model = Permission
        fields ='__all__'

class GroupSerializer(serializers.HyperlinkedModelSerializer):
    """ Add group serializer """
    url = serializers.HyperlinkedIdentityField(view_name="customuser:groups-detail")
    permissions = PermissionSerializer(many=True)

    class Meta:
        model = Group
        fields = ['url', 'name', 'permissions']

对于 rbac/api/viewsets.py:

from rest_framework import viewsets
from customuser.models import CustomUser
from django.contrib.auth.models import Group, Permission
from .serializers import CustomUserSerializer, GroupSerializer, PermissionSerializer
from django.utils.decorators import method_decorator


from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
from rest_framework.authentication import TokenAuthentication


class CustomUserViewSet(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = CustomUserSerializer
    # remove these two lines to remove auth
    authentication_classes = [TokenAuthentication]
    authentication_classes = [IsAuthenticated]

class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows view/create/edit/delete groups.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    # remove these two lines to remove auth
    authentication_classes = [TokenAuthentication]
    authentication_classes = [IsAuthenticated]

class PermissionViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Permission.objects.all()
    # remove these two lines to remove auth
    authentication_classes = [TokenAuthentication]
    authentication_classes = [IsAuthenticated]

如果您还不知道,构建 django 的 Group 类与 Permission 类具有多对多关系。因此,您应该在GroupSerializer 类中遵循相同的方法。在 Group 序列化器类中实例化权限序列化器类并传递many=True

这样,当您创建一个组时,您将能够从 api 将权限传递给它。

在我称为rbac 的应用程序中,您可以创建另一个url.py 文件并添加以下代码:

rbac/url.py:

from django.urls import path, include
from .api.viewsets import CustomUserViewSet, GroupViewSet, PermissionViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('customuser', CustomUserViewSet, basename='customuser')
router.register('groups', GroupViewSet, basename='groups')
router.register('permission', PermissionViewSet, basename='permission')


app_name='customuser'

urlpatterns = [
    path('', include(router.urls)),
]

(不要忘记将这个 url.py 包含()到主 url.py)

如果您将通过令牌对您的用户进行身份验证,则应在您的 settings.py 中添加您的 rbac 应用程序、rest_frameworkrest_framework.token

settings.py:

...
INSTALLED_APPS = [
   ...
    'rbacr', 
    'rest_framework', 
    'rest_framework.authtoken'
]

# if you created a customUser model as AbstractUSer
AUTH_USER_MODEL = 'rbac.CustomUser'


REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.DjangoModelPermissions',<==== SET THE CORE DJANGO PERMISSION INSTEAD
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
}

像这样,您的端点应该如下所示:

api/根目录:

{
    "customuser": "http://127.0.0.1:8000/api/customuser/",
    "groups": "http://127.0.0.1:8000/api/groups/",
    "permission": "http://127.0.0.1:8000/api/permission/"
}

api/customuser:

{
        "id": 2,
        "is_superuser": false,
        "username": "anyname",
        "first_name": "",
        "last_name": "",
        "email": "",
        "password": "pbkdf2_sha256$260000$gD........",
        "is_staff": true,
        "is_active": true,
        "date_joined": "2021-05-24T02:16:00Z",
        "last_login": "2021-05-26T02:57:30.215345Z",
        "groups": [
            3,   <==== 
            4    <==== 
        ]
    }

这些是使用 drf api 本身创建的组。

api/组:

[
    {
        "url": "http://127.0.0.1:8000/api/groups/1/",
        "name": "admin_group",
        "permissions": [
            {
                "id": 21,
                "name": "Can add user",
                "codename": "add_customuser",
                "content_type": 6
            },
            {
                "id": 25,
                "name": "Can view user",
                "codename": "can_view_user",
                "content_type": 6
            },
            {
                "id": 22,
                "name": "Can change user",
                "codename": "change_customuser",
                "content_type": 6
            },
            {
                "id": 23,
                "name": "Can delete user",
                "codename": "delete_customuser",
                "content_type": 6
            },
            {
                "id": 24,
                "name": "Can view user",
                "codename": "view_customuser",
                "content_type": 6
            }
        ]
    },
    {
        "url": "http://127.0.0.1:8000/api/groups/2/",
        "name": "insurer_group",
        "permissions": [
            {
                "id": 25,
                "name": "Can view user",
                "codename": "can_view_user",
                "content_type": 6 <======= CUSTOM USER ID
            }
        ]
    },
    {
        "url": "http://127.0.0.1:8000/api/groups/3/",
        "name": "whatever_group",
        "permissions": [] <=====  ONLY VIEW --- NEED A SMALL CHANGE TO REMOVE VIEW
    }
]

对于 api/permissions 将显示所有类/表的所有权限。

使用这种方法,您可以创建具有自定义权限的组并将它们分配给用户,如第一个端点所示。每个组将在customuser 端点中有一个id,然后,如果需要,您可以添加一个脚本来修改它们以显示名称。像这样,您将能够根据需要扩展管理员以使用并为每个组分配权限并向用户添加多个组。在我看来,组也可以被视为角色。

我建议你检查一下:

1-DjangoModelPermissions 2- 姜戈Group and Permissions

我是 django 的中级人员,如果您对这个问题有更好的答案,我将不胜感激。由于 django 关于这个主题的答案很少。

【讨论】:

    猜你喜欢
    • 2015-05-10
    • 2023-03-17
    • 2018-08-06
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    相关资源
    最近更新 更多