Django实战【六】—权限管理系统rbac组件实现

一、权限管理rbac组件

1.权限管理组件的实现思路

表结构分析

rbac的意思之前我详细提过,就是基于角色的访问权限控制,其实说白了啊,就是针对不同的用户角色, 给他们分配了访问哪些url的权利,因为在实际工作场景中,不同分工的人之间的业务也应该是各自来展开的。

也就是说权限本质上是一个url访问路径,而在我们实现的rbac组件中,权限是分配到对应的角色下,然后角色和用户之间又是一层多对多的关系。

有人会问,既然你是想要给用户分配不同的权限,那么为什么不直接单独给用户来分配权限,而是要通过角色表来呢?其实这里涉及到的是一种编程思想。

  • 如果我们用户数量很多,权限也很多,那么这么多用户,每一个用户都需要单独分配不同的权限,每个用户的权限也可能很多,这样在权限分配的时候会很繁琐。
  • 而通过角色表,将不同角色的权限进行统一的划分,即时你用户再多,权限再多,角色数量总归不会太多。这个时候我们只需要第一次指定好权限和角色之间的对应关系,以后只需要关注用户和角色之间的关系,这样就大大的减少了权限分配业务量,而且整体的关系也更加明朗。
实现思路
  • 访问权限

由于我们是要对每个用户的权限来限制,我们想一想什么地方能够做到呢?如果你django基础扎实,那么你很快就能想到中间件,中间件的process_request方法就是对所有过来的请求做一些全局的处理。

那么我们又该如何是每个用户的权限有区分呢?这种因角色不同而不同的数据肯定不可能通过全局来存储,肯定是将对应的权限信息存放在自己独有的空间里,这样的话我们就不难想到session,还记的session把?每个用户用来保存标识客户端的信息,其实session还可以存储其他的信息,比如我们这里的用户权限信息等等。

  • 菜单权限

权限验证思路有了,现在的具体情况是如果某个用户有某个权限,我们让他顺利访问,如果他没有某个权限,但是他有这个url权限的链接显示,结果我们给人家展示了一个大黄页,你没有权限。想想都角色有点脑残是吧!用户体验极差,卷铺盖回家把。

那么这里改怎么处理呢,其实在给用户权限的时候,也应当分配好用户所拥有的菜单权限,也就是是够给用户展示的权限。具体的实现就是根据用户权限,来确定他对应拥有的菜单权限,从而在前端页面展示出来。

  • 访问权限和菜单权限的注入

访问权限和菜单权限思路都有了,就涉及到什么时候注入了,我们知道权限是针对用户来的,那么这些权限的注入当然也是应该在用户登录成功的一瞬间就注入到这次会话的session中,这样大致的过程也就迎刃而解了。

img

2.前期页面准备

为了展示二级菜单效果,我们增加了一个私户展示页面,和公户页面同属于客户信息展示下的二级菜单。班级课程记录展示和学员学习记录展示属于教学信息展示页面下二级菜单。

同时为了显示没有子菜单的一级菜单效果,还增加了一个主页url权限,主页没有子菜单,而且主页所有人都可以访问。

主页url

我写在项目urls中,也就是ObCRM/urls.py中

from customer.views import customer
urlpatterns = [
    # 主页url
    url(r'^index/', customer.Index.as_view(),name="index"),
]
主页视图函数

主页视图我放在customer下views/customer.py中了。

# 主页
class Index(views.View):
    @method_decorator(login_required)  # 装饰器函数验证是否登录
    def dispatch(self, request, *args, **kwargs):
        res = super().dispatch(request, *args, **kwargs)
        return res
    def get(self,request):
        # 展示主页
        return render(request,"index.html")
主页html文件

这个主页我随便拷贝的模板,没有具体内容,继承的也是base页面,写在customer应用下templates中。

{% extends 'BASE.html' %}
{% block head %}
    {
  { block.super }}
{% endblock head %}

{% block title %}
    欢迎使用AliCRM系统
{% endblock title %}
{% block content %}
    这是主页
{% endblock content %}

{% block js %}
    {
  { block.super }}
{% endblock js %}

index.html
私户展示url

customer应用下urls中

# 私户数据展示
url(r'^private/list/', customer.PrivateList.as_view(), name="private_list"),
私户展示视图

私户展示我就简单实现了搜索,添加,编辑,删除等都是同样的,所以这里就不再实现了。

# 私户数据展示
class PrivateList(views.View):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        res = super().dispatch(request, *args, **kwargs)
        return res

    def get(self, request):
        condition = request.GET.get("condition", "")
        query = request.GET.get("q", "")
        condition = condition + "__contains"
        q = Q()  # Q实例化生成q对象,q对象可以帮我们拼接字符串为 condition__contians= xx的关键字参数传到filter中。
        q.children.append((condition, query))

        if condition and query:  # 如果有查询调参数,两个参数都有,根据查询参数查询后找到数据
            all_customers = models.Customer.objects.filter(q, consultant=request.user).order_by("-pk")
        else:  # 判断有没有查询参数,只有有一个没有参数,就查询所有公户数据
            all_customers = models.Customer.objects.filter(consultant=request.user).order_by("-pk")

        # 开始分页展示
        data_counts = all_customers.count()

        # 生成一个分页对象
        paginator = Paginator(request, data_counts, 10)

        # 获取当前页展示数据的范围
        try:  # 异常是否查到了数据,查到了才切片,不然会报错
            all_customers = all_customers[paginator.start:paginator.end]
        except Exception:
            pass

        # 获取分页的标签
        paginator_tag = paginator.paginate()  # 调用定义好的分页方法

        # 获取跳转页的标签
        jump_tag = paginator.jump_page()  # 调用定义好的跳转页方法

        return render(request, "private_list.html",
                      {
   "all_customers": all_customers, "paginator_tag": paginator_tag, "jump_tag": jump_tag})

私户展示视图类
私户展示html

私户展示html,与公户区别不大。customer应用下templates中

{% extends 'BASE.html' %}
{% load static %}
{% block head %}
    {
  { block.super }}
{% endblock head %}
{% block title %}
        私户信息展示
{% endblock title %}
{% block content %}
    <div class="row">
        <div class="col-xs-12">
            <div class="box">
                <div class="box-header">
                    <h3 class="box-title"></h3>
                    <form action="" method="get" class="navbar-form navbar-left">
                        <div class="input-group">
                            <div class="input-group-btn btn-info">
                                <select name="condition" id="search" class="btn input-group-sm btn-info"
                                        style="border: 0">
                                    <option value="" readonly>条件</option>
                                    <option value="qq_name">昵称</option>
                                    <option value="qq">QQ号</option>
                                </select>
                            </div>
                            <input type="text" name="q" class="form-control" placeholder="Search...">
                            <span class="input-group-btn">
                                <button type="submit" id="search-btn" class="btn btn-flat">
                                    <i class="fa fa-search"
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RBAC(Role-Based Access Control)是一种基于角色的访问控制,它将权限授予角色,然后将角色授予用户。在Django中,可以使用django-guardian或django-rules等第三方库来实现RBAC权限管理,也可以自己编写代码实现。 下面是一个基于Django自己编写的简单RBAC权限管理系统实现过程: 1. 定义权限模型 在Django中,可以通过定义模型来表示权限。例如,可以定义一个Permission模型,用来表示系统中的所有权限: ``` from django.db import models class Permission(models.Model): name = models.CharField(max_length=255, unique=True) codename = models.CharField(max_length=100, unique=True) ``` 其中name字段表示权限的名称,codename字段表示权限的代码名称。 2. 定义角色模型 同样地,可以定义一个Role模型,用来表示系统中的所有角色: ``` from django.db import models class Role(models.Model): name = models.CharField(max_length=255, unique=True) permissions = models.ManyToManyField('Permission') ``` 其中name字段表示角色的名称,permissions字段表示角色拥有的权限。 3. 定义用户模型 可以使用Django自带的User模型或者自己定义一个用户模型。在用户模型中,可以添加一个roles字段,用来表示用户所拥有的角色: ``` from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): roles = models.ManyToManyField('Role') ``` 4. 编写权限检查装饰器 在Django中,可以使用装饰器来检查用户是否拥有某个权限。下面是一个简单的权限检查装饰器的实现: ``` from functools import wraps from django.http import HttpResponseForbidden def permission_required(perm): def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): if not request.user.has_perm(perm): return HttpResponseForbidden() return view_func(request, *args, **kwargs) return _wrapped_view return decorator ``` 在上面的代码中,permission_required装饰器接受一个权限codename作为参数,返回一个装饰器函数。这个装饰器函数接受一个视图函数作为参数,返回一个新的视图函数。新的视图函数在执行前会检查用户是否拥有该权限,如果没有则返回403禁止访问状态码。 5. 在视图函数中使用权限检查装饰器 在需要进行权限检查的视图函数上加上permission_required装饰器即可: ``` @permission_required('app.view_model') def my_view(request): # do something ``` 在上面的代码中,my_view函数需要拥有view_model权限才能访问。 6. 编写角色管理视图 可以编写一个简单的角色管理视图,用来管理系统中的角色和权限: ``` from django.shortcuts import render from .models import Role, Permission def role_list(request): roles = Role.objects.all() return render(request, 'role_list.html', {'roles': roles}) def role_detail(request, role_id): role = Role.objects.get(id=role_id) permissions = Permission.objects.all() return render(request, 'role_detail.html', {'role': role, 'permissions': permissions}) ``` 在上面的代码中,role_list函数返回所有角色的列表,role_detail函数返回指定角色的详细信息和所有权限的列表。 7. 编写用户角色管理视图 可以编写一个简单的用户角色管理视图,用来管理用户和角色的关联关系: ``` from django.shortcuts import render from django.contrib.auth.models import User from .models import Role def user_list(request): users = User.objects.all() return render(request, 'user_list.html', {'users': users}) def user_detail(request, user_id): user = User.objects.get(id=user_id) roles = Role.objects.all() return render(request, 'user_detail.html', {'user': user, 'roles': roles}) ``` 在上面的代码中,user_list函数返回所有用户的列表,user_detail函数返回指定用户的详细信息和所有角色的列表。 8. 编写用户角色管理视图的表单处理函数 可以编写一个简单的表单处理函数,用来处理用户和角色的关联关系: ``` from django.shortcuts import redirect from django.contrib.auth.models import User from .models import Role def assign_role(request, user_id): if request.method == 'POST': user = User.objects.get(id=user_id) role_ids = request.POST.getlist('roles') roles = Role.objects.filter(id__in=role_ids) user.roles.set(roles) return redirect('user_detail', user_id=user_id) ``` 在上面的代码中,assign_role函数接受一个用户ID作为参数,从POST请求中获取选中的角色ID,将这些角色和用户关联起来,然后重定向到用户详细信息页面。 9. 编写角色管理视图的表单处理函数 可以编写一个简单的表单处理函数,用来处理角色和权限的关联关系: ``` from django.shortcuts import redirect from .models import Role, Permission def assign_permission(request, role_id): if request.method == 'POST': role = Role.objects.get(id=role_id) permission_ids = request.POST.getlist('permissions') permissions = Permission.objects.filter(id__in=permission_ids) role.permissions.set(permissions) return redirect('role_detail', role_id=role_id) ``` 在上面的代码中,assign_permission函数接受一个角色ID作为参数,从POST请求中获取选中的权限ID,将这些权限和角色关联起来,然后重定向到角色详细信息页面。 10. 编写模板 最后,可以编写一些简单的模板来渲染上述视图函数返回的数据。 例如,可以编写role_list.html模板来渲染角色列表: ``` <ul> {% for role in roles %} <li><a href="{% url 'role_detail' role.id %}">{{ role.name }}</a></li> {% endfor %} </ul> ``` 可以编写role_detail.html模板来渲染角色详细信息和权限列表: ``` <h1>{{ role.name }}</h1> <h2>Permissions</h2> <form method="post" action="{% url 'assign_permission' role.id %}"> {% csrf_token %} {% for permission in permissions %} <label> <input type="checkbox" name="permissions" value="{{ permission.id }}" {% if permission in role.permissions.all %}checked{% endif %}> {{ permission.name }} </label> {% endfor %} <button type="submit">Save</button> </form> ``` 可以编写user_list.html模板来渲染用户列表: ``` <ul> {% for user in users %} <li><a href="{% url 'user_detail' user.id %}">{{ user.username }}</a></li> {% endfor %} </ul> ``` 可以编写user_detail.html模板来渲染用户详细信息和角色列表: ``` <h1>{{ user.username }}</h1> <h2>Roles</h2> <form method="post" action="{% url 'assign_role' user.id %}"> {% csrf_token %} {% for role in roles %} <label> <input type="checkbox" name="roles" value="{{ role.id }}" {% if role in user.roles.all %}checked{% endif %}> {{ role.name }} </label> {% endfor %} <button type="submit">Save</button> </form> ``` 至此,一个简单的RBAC权限管理系统就完成了。当然,实际应用中可能需要更复杂的权限管理需求,可以根据具体情况进行扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值