如何在Django中实现基于角色的访问控制

来源:安卓APP网作者:冷风头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何在Django中实现基于角色的访问控制》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何在Django中实现基于角色的访问控制》有用,将其分享出去将是对创作者最好的鼓励。

基于角色的访问控制也就是RBAC,是很多Web项目常用的权限管理模型,核心思路是将权限关联到角色,再把角色分配给用户,用户通过所属角色获得对应权限,避免直接给用户分配权限带来的管理复杂度。在Django框架中,我们可以基于自带的用户系统扩展实现这套逻辑。

如何在Django中实现基于角色的访问控制

核心模型设计

首先需要扩展Django的默认用户模型,新增角色表和权限关联表,这里我们使用自定义用户模型的方式实现,首先需要定义角色模型:

from django.db import models
from django.contrib.auth.models import AbstractUser

# 角色模型,存储不同角色信息
class Role(models.Model):
    name = models.CharField(max_length=50, unique=True, verbose_name="角色名称")
    # 角色对应的权限列表,这里用逗号分隔的权限标识存储,也可以单独建权限表关联
    permissions = models.TextField(verbose_name="权限列表", blank=True)
    
    class Meta:
        verbose_name = "角色"
        verbose_name_plural = "角色"
    
    def __str__(self):
        return self.name

# 自定义用户模型,关联角色
class CustomUser(AbstractUser):
    # 一个用户可以拥有多个角色,多对多关联
    roles = models.ManyToManyField(Role, verbose_name="用户角色", blank=True)
    
    class Meta:
        verbose_name = "自定义用户"
        verbose_name_plural = "自定义用户"
    
    def get_permissions(self):
        # 获取用户所有角色的权限,去重后返回
        permissions = set()
        for role in self.roles.all():
            if role.permissions:
                # 假设权限是按逗号分隔的字符串存储,比如"view_article,edit_article"
                perms = role.permissions.split(",")
                permissions.update(perms)
        return permissions

权限校验实现方式

方式一:使用装饰器校验权限

我们可以自定义一个装饰器,在视图函数执行前校验当前用户是否拥有对应权限,适用于单个视图的权限控制:

from functools import wraps
from django.http import HttpResponseForbidden
from django.contrib.auth.decorators import login_required

def permission_required(perm):
    """
    权限校验装饰器,参数perm为需要的权限标识
    """
    def decorator(view_func):
        @wraps(view_func)
        @login_required  # 先校验用户是否登录
        def wrapper(request, *args, **kwargs):
            user = request.user
            # 获取用户所有权限
            user_perms = user.get_permissions()
            if perm in user_perms:
                return view_func(request, *args, **kwargs)
            else:
                return HttpResponseForbidden("你没有访问该资源的权限")
        return wrapper
    return decorator

使用这个装饰器的示例如下,比如编辑文章的视图需要edit_article权限:

from django.shortcuts import render
from .decorators import permission_required

@permission_required("edit_article")
def edit_article_view(request):
    return render(request, "edit_article.html")

方式二:使用中间件全局校验

如果需要全局校验某些路径的访问权限,可以自定义中间件,在请求到达视图前统一处理:

from django.http import HttpResponseForbidden
from django.urls import resolve

class RbacMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 定义不需要校验的路径,比如登录页、静态资源路径
        self.exempt_urls = ["/login/", "/admin/"]
    
    def __call__(self, request):
        # 如果用户未登录,直接跳过校验,由login_required处理
        if not request.user.is_authenticated:
            return self.get_response(request)
        
        # 获取当前请求的路径
        current_path = request.path
        # 如果路径在豁免列表中,直接放行
        if any(current_path.startswith(url) for url in self.exempt_urls):
            return self.get_response(request)
        
        # 解析当前路径对应的视图函数,获取需要的权限(这里可以提前定义路由和权限的映射)
        # 简单示例:假设路径包含edit的都需要edit_article权限
        if "edit" in current_path and "edit_article" not in request.user.get_permissions():
            return HttpResponseForbidden("你没有访问该资源的权限")
        
        return self.get_response(request)

定义好中间件后,需要在Django的settings.py中注册:

MIDDLEWARE = [
    # 其他中间件
    "your_app.middleware.RbacMiddleware",
]

# 替换默认用户模型
AUTH_USER_MODEL = "your_app.CustomUser"

角色分配与管理

我们可以写一个管理视图,给管理员提供分配角色的功能,比如给指定用户添加角色:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import permission_required
from .models import CustomUser, Role

@permission_required("manage_user")
def assign_role_view(request, user_id):
    user = CustomUser.objects.get(id=user_id)
    if request.method == "POST":
        # 获取前端提交的角色ID列表
        role_ids = request.POST.getlist("roles")
        # 清空用户原有角色
        user.roles.clear()
        # 添加新选中的角色
        for role_id in role_ids:
            role = Role.objects.get(id=role_id)
            user.roles.add(role)
        return redirect("user_list")
    # 获取所有角色
    roles = Role.objects.all()
    return render(request, "assign_role.html", {"user": user, "roles": roles})

注意事项

  • 权限标识建议统一规范,比如使用资源名加操作的形式,如view_user、edit_user、delete_user,便于管理
  • 如果权限较多,建议单独建立权限表,和角色做多对多关联,避免角色表的permissions字段过长
  • 中间件校验适合全局通用的权限规则,单个视图的特殊权限建议使用装饰器实现,更灵活
  • 自定义的权限校验逻辑需要做好异常处理,避免因为权限查询异常导致服务不可用

Django基于角色的访问控制RBAC权限管理修改时间:2026-07-04 09:57:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。