【发布时间】:2019-05-01 16:20:59
【问题描述】:
关于我应该使用什么来集成 RBAC 和 DRF 有什么建议吗?我已经看过 django-rest-framework-roles 和 django-guardian 但看起来都不太有希望。您的反馈将不胜感激。提前致谢。
【问题讨论】:
标签: django rest authorization rbac abac
关于我应该使用什么来集成 RBAC 和 DRF 有什么建议吗?我已经看过 django-rest-framework-roles 和 django-guardian 但看起来都不太有希望。您的反馈将不胜感激。提前致谢。
【问题讨论】:
标签: django rest authorization rbac abac
我所做的是为Users、Groups 和Permissions 创建端点,并将DjangoModelPermissions 与TokenAuthentication 结合使用。
您可以将User 模型覆盖为abstractUser,也可以按原样使用它。
为Users、Permissions 和Group 创建序列化程序。
我个人遵循这种方法:
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_framework 和 rest_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 关于这个主题的答案很少。
【讨论】: