rbac基于角色的权限管理开发

一、model模块


权限表结构设计:
权限表结构设计

from django.db import models


class User(models.Model):
    """
    用户表
    """
    username = models.CharField(verbose_name='用户名', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=64)
    email = models.EmailField(verbose_name='邮箱')

    def __str__(self):
        return self.username


class Role(models.Model):
    """
    角色表
    """
    caption = models.CharField(verbose_name='角色', max_length=32)

    def __str__(self):
        return self.caption


class User2Role(models.Model):
    """
    用户角色关系表
    """
    user = models.ForeignKey(User, verbose_name='用户', related_name='roles',on_delete='')
    role = models.ForeignKey(Role, verbose_name='角色', related_name='users',on_delete='')

    def __str__(self):
        return '%s-%s' % (self.user.username, self.role.caption,)


class Menu(models.Model):
    """
    菜单表
    """
    caption = models.CharField(verbose_name='菜单名称', max_length=32)
    parent = models.ForeignKey('self', verbose_name='父菜单', related_name='p', null=True, blank=True,on_delete='')

    def __str__(self):
        prev = ""
        parent = self.parent
        while True:
            if parent:
                prev = prev + '-' + str(parent.caption)
                parent = parent.parent
            else:
                break
        return '%s-%s' % (prev, self.caption,)


class Permission(models.Model):
    """
    权限
    """
    caption = models.CharField(verbose_name='权限', max_length=32)
    url = models.CharField(verbose_name='URL正则', max_length=128)
    menu = models.ForeignKey(Menu, verbose_name='所属菜单', related_name='permissions',null=True,blank=True,on_delete='')

    def __str__(self):
        return "%s-%s" % (self.caption, self.url,)


class Action(models.Model):
    """
    操作:增删改查
    """
    caption = models.CharField(verbose_name='操作标题', max_length=32)
    code = models.CharField(verbose_name='方法', max_length=32)

    def __str__(self):
        return self.caption


class Permission2Action2Role(models.Model):
    """
    权限操作关系表
    """
    permission = models.ForeignKey(Permission, verbose_name='权限URL', related_name='actions',on_delete='')
    action = models.ForeignKey(Action, verbose_name='操作', related_name='permissions',on_delete='')
    role = models.ForeignKey(Role, verbose_name='角色', related_name='p2as',on_delete='')

    class Meta:
        unique_together = (
            ('permission', 'action', 'role'),
        )

    def __str__(self):
        return "%s-%s-%s" % (self.permission, self.action, self.role,)

二、urls.py模块


urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^auth-login.html$', views2.login),
    url(r'^auth-index(-\d+)*.html$', views2.index),
]

三、views.py模块


from django.shortcuts import render,redirect,HttpResponse
from app02 import models

# Create your views here.
def login(request):
    if request.method == 'GET':
        return render(request, 'login2.html')
    else:
    #     # 根据用户登录信息获得所有权限
    #     object = models.User.objects.filter(username='tom').first()  # 假定根据登陆信息获得用户名为tom
    #     # 根据用户对象获得对应的所有角色(有2种方式)
    #     role_list = models.User2Role.objects.filter(user_id=object.id)  # 方式一:正向操作 获得[User2Role,User2Role,User2Role]
    #     # 方式二:反向操作,通过users跨表到user表中的user_id字段,获得对应的role表的所有id,从而获得所有role(推荐该方法)
    #     role_list = models.Role.objects.filter(users__user_id=object.id)
    #
    #     # 根据角色对象,获得所有权限,并去重
    #     from django.db.models import Count
    #     # models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url', 'action__code').annotate(c = Count('id'))
    #     # 推荐下面方式,不会生成新的字段c
    #     permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url', 'action__code').distinct()
    #     # 获得结果如下所示:
    #     """
    #     [
    #     {permission_url: '/index.html', action_code:'GET'},
    #     {permission_url: '/index.html', action_code:'POST'},
    #     {permission_url: '/index.html', action_code:'DEL'},
    #     {permission_url: '/index.html', action_code:'Edit'},
    #     {permission_url: '/order.html', action_code:'GET'},
    #     {permission_url: '/order.html', action_code:'POST'},
    #     {permission_url: '/order.html', action_code:'DEL'},
    #     {permission_url: '/order.html', action_code:'Edit'},
    # ]
    # """
        # 再通过for循环将数据库中查出的数据转换成如下格式:
        user_permission_dict = {
            '/ah-index.html': ["GET","POST","DEL","Edit"],
            '/order.html':  ["GET","POST","DEL","Edit"],
            '/auth-index(-\d+)*.html':  ["GET","POST","DEL","Edit"],  # 可接收通过格式 '/auth-index-3.html', '/auth-index.html'
        }

        # 将用户的对应的权限放入session中,当访问其它链接时,可直接从session中进行校验是否存在该权限
        request.session['user_permission_dict'] = user_permission_dict
        return HttpResponse('登陆成功')

def index(request):
    return HttpResponse('登陆成功,你拥有了权限,恭喜你看见了我')

三、html模版


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="POST" action="/auth-login.html">
    {% csrf_token %}
    <input type="text" name="user/">
    <input type="submit" value="提交/">
</form>
</body>
</html>

四、自定义中间件


# 添加中间件,控制权限
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
import re
class M1(MiddlewareMixin):
    def process_request(self, request, **kwargs):
        valid = ['/auth-login.html', '/index.html'] # 设置白名单,不进行校验
        if request.path_info not in valid:  # /auth-index
            action = request.GET.get('md')   # 获得操作指令
            user_permission_dict = request.session.get['user_permission_dict']  # 获得权限字典
            if not user_permission_dict:
                return HttpResponse('无权限')

            flag = False
            if request.path_info != '/favicon.ico':   # 每一次请求,request.path_info会获得两个值,请求url和/favicon
                for k, v in user_permission_dict.items():
                    if re.match(k, request.path_info):  # 正则匹配,假定数据库的为/index-(\d+).html,则/auth-index-3.html等格式可同样包括
                        if action in v:
                            flag = True     # 表示该用户拥有该权限操作,继续往下执行
                            break
                if not flag:
                    return HttpResponse('无权限')

六、setting.py模块


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middleware.md.M1',   # 将该中间件注册
]
展开阅读全文

没有更多推荐了,返回首页