码迷,mamicode.com
首页 > 其他好文 > 详细

Djang之基于角色的权限控制(RBAC)

时间:2020-01-09 22:50:45      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:match   文件   实现   当当   author   map   stat   __str__   dep   

一、后端部分

1. models设计

实现:特定角色拥有访问特定url路径,角色关联用户,以此来控制用户的访问。

如:管理员:可以访问所有的url地址,甲关联了管理员,则甲拥有访问所有url地址的权限,普通用户:只拥有访问查看数据(查看某个页面)的url地址,乙关联普通用户,乙就只拥有普通用户的权限

2.models实现

技术图片
class Permission(models.Model):
    url = models.CharField(max_length=64, verbose_name=权限)
    title = models.CharField(max_length=32, verbose_name=标题)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name_plural = 权限管理


class Role(models.Model):
    name = models.CharField(max_length=32, verbose_name=角色)
    permissions = models.ManyToManyField(Permission, verbose_name=角色拥有的权限, blank=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = 角色管理


class User(models.Model):
    username = models.CharField(max_length=32, verbose_name=用户名, unique=True)
    password = models.CharField(max_length=32, verbose_name=密码)
    roles = models.ManyToManyField(Role, verbose_name=用户的角色, blank=True)

    def __str__(self):
        return self.username

    class Meta:
        verbose_name_plural = 用户管理
models.py

3. 将登陆成功的用户的权限(url地址)写入到session中

技术图片
from rbac import models
from django.shortcuts import redirect, render, HttpResponse
from django.conf import settings

def login(request):
    if request.method == POST:
        username = request.POST.get(username)
        password = request.POST.get(password)
        obj = models.User.objects.filter(username=username, password=password).first()
        if not obj:
            error = 用户名或密码错误
            return render(request, login.html, locals())

        # 获取权限的信息
        permission= obj.roles.all().filter(permissions__url__isnull=False).values(permissions__url,
                                                                            permissions__title,
                                                                          ).distinct()

        # 获取登录用户的权限列表(能访问的url地址)
        request.session[permission] = list(permission)
        request.session[is_login] = 1
        return redirect(index)

    return render(request, login.html, locals())    
views.py

4. 白名单与免认证名单

技术图片
#白名单:无需登录,就可以访问的路径
WHITE_LIST = [
    r/login/,
    r^/admin/,
]

#免认证名单 登录之后的用户都可以访问的url
PUBLIC_LIST = [
    r/index/,
]
settings.py

5. 从中间件中获取request.session中的permission权限(url地址列表)

技术图片
from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from django.shortcuts import redirect, HttpResponse
import re

class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        url = request.path_info  # 当前页面的url地址
        # 白名单 :登陆、注册、admin
        for i in settings.WHITE_LIST: # WHITE_LIST是配置在settings.py文件中的地址白名单
            if re.match(i, url):
                return

        # 登陆验证
        is_login = request.session.get(is_login)
        if is_login != 1:
            return redirect(login)

        # 免认证 登录之后所有人都能访问的地址如:后台首页
        for i in settings.PUBLIC_LIST:
            if re.match(i, url):
                return

        # 权限验证 我们在登录函数中将当前登录用户中的所有权限(url地址列表)都放入到了session中,这里拿出来和当前的url地址进行匹配。
        permission = request.session.get(permission )
        for i in permission:
            if re.match(r^{}$.format(i[url]), url):
                return
        return HttpResponse(没有权限,请联系管理员!)
middlewares/rbac.py

二、前端部分

6.  自定模板标签,渲染数据

注意:模板标签存放的目录必须为tamplatetags

技术图片
# -*- coding: utf-8 -*-
# __author__ = "maple"
from django import template
from django.conf import settings
import re
register = template.Library()
@register.inclusion_tag(menu_tag.html) # menu_tag.html文件时配合该函数做模板渲染的,是该标签的一部分
def menu(request):
    """
   当当前url地址与menu_list中的url地址能够匹配到时,给menu_list中    
   的匹配到的地址添加一个键值对{"class":"active"}
    """
    url = request.path_info
    # 添加激活的样式
    for i in menu_list:
        if re.match(f^{i["url"]}$,url):
            i[class] = active
            break
    return {menu_list:menu_list}

# menu_list的数据格式如:
#    [{‘url‘:‘/customer/list/‘},{‘url‘:‘/customer/add/‘},]
# 假如当前url地址为:/customer/list/时
#    则 menu_list中数据会变为:
#    [{‘url‘:‘/customer/list/‘,"class":"active"},{‘url‘:‘/customer/add/‘},]
my_tags.py

my_tags文件中通过装饰器渲染的标签内容

技术图片
<div class="static-menu">
    {% for menu in menu_list %}
        <a href="{{ menu.url}}" class="{{menu.class}}">{{ menu.title}}</a>
    {% endfor %}
</div>
menu_tag.html

7. 应用自定义标签

技术图片
    ...
<div class="left-menu">
   <div class="menu-body">
        {% load my_tags %}
        {% menu request %}
</div>
    ...    
顶级模板文件中

Djang之基于角色的权限控制(RBAC)

标签:match   文件   实现   当当   author   map   stat   __str__   dep   

原文地址:https://www.cnblogs.com/kindvampire/p/12173525.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!