基于角色的访问控制 (RBAC) 是一种安全模型,它限制访问资源。在 Django 中,你可以通过利用内置的认证与授权框架来实现 RBAC,这允许你定义角色、分配权限并控制对应用程序特定部分的访问权限。本文提供了一个全面的指南说明,介绍如何在 Django 中使用自定义权限、组和中间件等来实现更复杂的 RBAC。
为什么使用基于角色的访问控制(RBAC)呢?RBAC(基于角色的访问控制)可以帮助以可扩展和可维护的方式管理用户权限,特别是在需要为多个用户设置不同访问权限的应用程序中。它能帮助您:
- 定义角色,并赋予它们特定的权限。
- 将这些角色分配给用户。
- 根据用户的角色,控制他们访问界面、模型等相关资源的权限。
在深入了解之前,理解Django的认证系统非常重要:
- 用户:代表一个单独的用户账户。
- 权限:代表执行特定操作的能力,例如添加或删除一个资源。
- 组:代表一个用户组。每个组可以拥有一套权限。
- 角色:在角色基础访问控制的上下文中,角色通常被表示为具有特定权限的组。
如果还没有的话,先创建一个新的Django项目和应用。
在终端中输入 `django-admin startproject myproject`
在终端中输入 `cd myproject`
在终端中输入 `python manage.py startapp myapp`
在 settings.py
文件的 INSTALLED_APPS
列表中添加你的新应用:
INSTALLED_APPS = [
...
'myapp',
...
]
配置文件中,INSTALLED_APPS
列表中包含 'myapp'
,例如:
INSTALLED_APPS = [
...
'myapp',
...
]
第2步:定义用户角色和权限
你可以为你的模型定义自定义权限。这些权限存储在数据库里,并可以分配给用户或用户组。
创建一个带有自定义权限设置的模型
我们可以在 myapp/models.py
文件中下面定义一个具有自定义权限的 Document
模型如下:
from django.db import models
from django.contrib.auth.models import User
class Document(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
permissions = [
("can_publish_document", "可以发布文章"),
("can_archive_document", "可以存档文章"),
]
def __str__(self):
return self.title
首先,运行以下命令来创建和应用迁移:
# 创建一个新的迁移文件
python manage.py makemigrations
# 应用最新的迁移
python manage.py migrate
让我们使用`python manage.py makemigrations`命令来创建新的数据库迁移吧。
接下来,我们使用`python manage.py migrate`命令来应用这些迁移。
使用组来创建用户角色设置
你可以使用Django的Group
模型来创建角色。每个组都可以有自己的特定权限。在myapp/management/commands/setup_roles.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group, Permission
from myapp.models import Document
class Command(BaseCommand):
help = '创建用户角色并分配权限'
def handle(self, *args, **kwargs):
# 创建角色
editor_group, created = Group.objects.get_or_create(name='Editor') # 创建 Editor 角色
publisher_group, created = Group.objects.get_or_create(name='Publisher') # 创建 Publisher 角色
admin_group, created = Group.objects.get_or_create(name='Admin') # 创建 Admin 角色
# 分配权限
publish_permission = Permission.objects.get(codename='can_publish_document') # 获取发布文档权限
archive_permission = Permission.objects.get(codename='can_archive_document') # 获取归档文档权限
# 将权限添加到各组
editor_group.permissions.add(publish_permission)
publisher_group.permissions.add(archive_permission)
admin_group.permissions.add(publish_permission, archive_permission)
self.stdout.write(self.style.SUCCESS('角色和权限已成功设置!'))
运行自定义命令来创建角色并分配权限,如下所示:
python manage.py 设置角色权限
步骤 3:给用户分配角色:
你可以通过Django的管理界面或者编写代码将这些角色分配给用户。
通过管理界面给角色分配权限
- 进入Django管理界面。
- 导航到用户部分,选择一个用户。
- 向下滚动到“组”部分,找到,将用户添加到所需的组中(例如,编辑、发布、管理)。
程序化分配角色
从 django.contrib.auth.models 导入 User, Group
# 将用户 'john_doe' 分配到 'Editor' 组
user = User.objects.get(username='john_doe')
editor_group = Group.objects.get(name='Editor')
user.groups.add(editor_group)
步骤 4: 在视图中实施访问控制
Django 提供了多种在视图中实现访问控制的方法,包括装饰器和基于类的混入方法。
使用如下的**@permission_required**
装饰器
@permission_required
装饰器会检查用户是否有特定权限,然后允许访问位于 myapp/views.py
的 view。
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
from django.http import HttpResponse
@permission_required('myapp.can_publish_document', raise_exception=True)
def publish_document(request):
return HttpResponse("恭喜,您有权发布文档了。")
在类视图中使用**PermissionRequiredMixin**
在基于类的视图中,你可以使用位于myapp/views.py
中的PermissionRequiredMixin
类。
导入 django.contrib.auth.mixins 中的 PermissionRequiredMixin
导入 django.views.generic 中的 TemplateView
class PublishDocumentView(PermissionRequiredMixin, TemplateView):
template_name = 'publish.html'
permission_required = 'myapp.can_publish_document'
该视图仅对拥有can_publish_document
权限的用户可见。
例如,您可以创建一个访问控制中间件来限制基于角色和权限的访问。访问控制中间件可以用来在整个应用程序中实施访问控制。例如在 myapp/middleware.py
文件中。
from django.shortcuts import redirect
from django.contrib.auth.models import Group
class 基于角色的访问控制中间类:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 跳过中间件以处理管理员和超级用户
if request.user.is_authenticated and not request.user.is_staff and not request.user.is_superuser:
if 用户组中不存在名为 'Admin' 的组:
# 如果用户不在 'Admin' 组,则重定向到无权限页面
if 请求路径不以 '/no-permission' 开头:
return redirect('/no-permission/')
response = self.get_response(request)
return response
在 settings.py
文件中加入 Middleware
要启用中间件,请将其添加到 settings.py
中的 MIDDLEWARE
列表或元组中。
MIDDLEWARE = [
...
'myapp.middleware.基于角色的访问控制中间件类',
...
]
第6步:自定义后台界面
Django的管理界面可以根据用户的权限自定义显示或隐藏特定模型或字段。
在管理界面中隐藏模型在 myapp/admin.py
中覆盖 get_queryset
方法以限制对特定对象的访问。
from django.contrib import admin
from .models import Document
class DocumentAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.groups.filter(name='Editor').exists():
return qs.filter(created_by=request.user)
return qs
admin.site.register(Document, DocumentAdmin)
在后台界面隐藏字段信息
隐藏特定字段,可以在你的管理类中覆盖 get_fields
方法。
class DocumentAdmin(admin.ModelAdmin):
# 文档管理员类
def get_fields(self, request, obj=None):
fields = super().get_fields(request, obj)
# 如果用户不是管理员组的成员,则从字段中移除'created_by'
if not request.user.groups.filter(name='Admin').exists():
fields.remove('created_by')
return fields
第7步:测试与调试
验证用户权限和角色
- 创建多个具有不同角色的测试用户。
- 测试对各种视图的访问,确保只有应该访问的用户才能访问。
- 通过用不同用户登录来测试中间件,验证他们是否如预期被重定向或允许访问。
调试小贴士
- 在您的视图或模板中使用
request.user.has_perm('app_label.permission_codename')
动态验证权限。 - 检查日志中的权限错误,并确保权限和组设置正确。
在 Django 中使用自定义权限、组和中间件实现基于角色的访问控制(RBAC),可以帮助你构建安全且易于维护的应用程序。按照本指南中的步骤,你可以创建符合特定需求的复杂访问控制体系。不论是简单的应用还是复杂的企业解决方案,RBAC 都提供了一种可扩展的方式来处理 Django 的用户权限和角色。
共同学习,写下你的评论
评论加载中...
作者其他优质文章