hadooprbac_基于角色权限管理:rbac具体代码实现

权限管理

创建一个rbac和app的应用,这个rbac主要是用来存放权限的,全称叫做基于角色权限控制

一、先看配置文件合适不,给创建的rbac在配置文件里面设置一下

找到INSTALLED_APPS=【'rbac'】

二、设计表结构

models中创建类:五个类,七张表

角色表:

用户表:

权限表:

组表:

菜单表:

角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)

用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)

所以有会多生成两张关系表

一个菜单下面有多个组

一个组下面有多个菜单

一个菜单下面有多个权限

from django.db import models

# Create your models here.

class Role(models.Model):

'''

角色表

'''

title = models.CharField(max_length=32,verbose_name="角色名")

permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True) # 建立用户表和角色表的多对多关系

def __str__(self):

return self.title

class Meta:

verbose_name_plural = "角色表"

class Group(models.Model):

caption = models.CharField(max_length=32,verbose_name="组名称")

menu = models.ForeignKey(to="Menu",verbose_name="所属菜单",default=1,related_name="menu")

class Menu(models.Model):

title = models.CharField(max_length=32)

class Permission(models.Model):

'''

权限表

'''

title = models.CharField(max_length=32,verbose_name="标题")

url = models.CharField(max_length=64,verbose_name="带正则的URL")

# is_mune = models.BooleanField(verbose_name="是否是菜单",default=0)

menu_gp = models.ForeignKey(verbose_name="组内菜单",to="Permission",blank=True,null=True) #自关联

#主页就可以设置为菜单,当点击菜单的时候才可以做具体的操作

codes = models.CharField(max_length=32,verbose_name="代码",default=1)

group = models.ForeignKey(to="Group",verbose_name="所属组",null=True) #新添加的字段记得设置默认值

def __str__(self):

return self.title

class Meta:

'''中文显示'''

verbose_name_plural = "权限表"

class UserInfo(models.Model):

'''

用户表

'''

username = models.CharField(max_length=32,verbose_name="用户名")

password = models.CharField(max_length=64,verbose_name="密码")

email = models.CharField(max_length=32,verbose_name="邮箱")

roles = models.ManyToManyField(to="Role",verbose_name="具有的所有角色",blank=True) #建立用户和角色的多对多关系

def __str__(self):

return self.username

class Meta:

verbose_name_plural = "用户表"

三、通过django admin录入权限数据

- 先创建一个超级用户

- 用户名 root

- 密码 zhy123456

- 在admin.py 中

from rbac import models

admin.site.register(models.Permission)

admin.site.register(models.Role)

admin.site.register(models.UserInfo)

这样的话上去的是英文的,如果你想让中文显示就在类中加一个类

class Meta:

verbose_name_plural = "权限表"

- 当你给关联字段录入数据的时候会有错误提示,那么在类中你的那个关联字段在加一个属性blank = True 可以为空

permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有权限", blank=True)

四、编写登录

用户登录后:

获取当前用户具有的所有角色

获取当前用户具有的所有权限(并且去重)

#获取当前的用户对象

user = models.UserInfo.objects.filter(username=name,password=password).first()

#获取当前用户的所有角色user.roles.all()

#获取当前用户的所有权限

permission_list = user.roles.all().values("permissions__title","permissions__url","permissions__is_mune").distinct()

print(permission_list)

登录成功之后初始化---把所有的url都拿出来并且保存到session里

1、可以建一个server的包,在里面建一个初始化的init_perssion.py文件

2、定义函数

#!usr/bin/env python

# -*- coding:utf-8 -*-

from rbac import models

from day7权限管理 import settings

def init_permission(user,request):

#获取当前的用户对象

'''

获取所有权限中的url并放在session中

:param user:

:param request:

:return:

'''

#user.roles.all()获取当前用户的所有角色

#获取当前用户的所有权限

permission_list = user.roles.all().values(

"permissions__id",

"permissions__title", #用户列表

"permissions__url", #url

"permissions__menu_gp", #组内菜单id,如果为null表示是菜单

"permissions__codes",

"permissions__group_id",

"permissions__group__menu__title", #菜单名称

"permissions__group__menu__id" #菜单id

).distinct()

print("-----------------",permission_list)

#菜单相关

sub_permisson_list = []

for item in permission_list:

tpl = {

"id":item["permissions__id"],

"title":item["permissions__title"],

"url":item["permissions__url"],

"menu_group_id":item["permissions__group_id"],

"menu_id":item["permissions__group__menu__id"],

"menu_title":item["permissions__group__menu__title"]

}

sub_permisson_list.append(tpl)

request.session[settings.PERMISSION_MENU_KEY] = sub_permisson_list

# 1、去掉不是菜单的url

# 菜单操作

# menu_list = []

# for item in permission_list:

# if not item["permissions__is_mune"]: # 如果不是菜单就继续

# continue

# else: # 否则是菜单的话就把菜单添加到列表里面

# tpl = {

# "menu_id": item["permissions__group__menu__id"],

# "menu_title": item["permissions__group__menu__title"],

# "title": item["permissions__title"],

# "url": item["permissions__url"],

# "active": False

# }

# menu_list.append(tpl)

# request.session[settings.PERMISSION_MENU_KEY] = menu_list #吧所有的菜单都放在session里面

# print("xcvxvxv", menu_list)

# 权限相关

result = {}

for item in permission_list:

group_id = item["permissions__group_id"]

url =item["permissions__url"]

code = item["permissions__codes"]

if group_id in result:

#如果在说明url和code已经生成了

result[group_id]["codes"].append(code)

result[group_id]["urls"].append(url)

else:

#如果不在就添加进去

result[group_id] ={

"codes":[code,],

"urls":[url]

}

# print(result)

#吧所有权限中的url字典放到session中

request.session[settings.PERMISSION_URL_DICT_KEY] = result

# # 打印的结果如下

# result = {

# 1: {

# "codes": ["list", "add", "del", "edit"]

# "urls": [

# "/userinfo/",

# "/userinfo/add" ,

# "/userinfo/del(\d+)/ ",

# "/userinfo/edit(\d+)/ ",

# ]

# },

# 2: {

# "codes": {"list", "add", "del", "edit"}

# "urls": [

# "/order",

# "/order/add" ,

# "/order/del(\d+)/ ",

# "/order/edit(\d+)/ ",

# ]

# }

# }

五、中间件

- 在setting里设置白名单(不用权限就可以访问)

#白名单

VALID_URL = [

"/login/",

"/admin.*/",

"/index/"

]

# ==================rabc==============

PERMISSION_URL_DICT_KEY="permissions_url_dict"

PERMISSION_MENU_KEY = "menu_list"

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',

'rbac.middlewears.rbac.Middle',

]

- 获取当前的url请求

- 获取session保存的权限信息

- 循环url进行正则匹配,如果匹配成功就有权访问,不成功就无法访问

用中间件的时候记得要在settings里面配置一下:

#!usr/bin/env python

# -*- coding:utf-8 -*-

import re

from django.shortcuts import render,HttpResponse,redirect

from django.conf import settings

class MiddlewareMixin(object):

def __init__(self, get_response=None):

self.get_response = get_response

super(MiddlewareMixin, self).__init__()

def __call__(self, request):

response = None

if hasattr(self, 'process_request'):

response = self.process_request(request)

if not response:

response = self.get_response(request)

if hasattr(self, 'process_response'):

response = self.process_response(request, response)

return response

class Middle(MiddlewareMixin):

def process_request(self,request):

#获取当前的url请求

current_url = request.path_info #拿到当前的路径

# print(request.path,current_url)

#获取Session中保存当前用户的权限,

# request.session.get("permissions_url_list")

# 如果当前的路径和session里面保存的url一样就break了,如果不一样就说明无权访问

for url in settings.VALID_URL:

# print(url,current_url)

if re.match(url,current_url):

return None #如果url是表名单白名单里面的,就让直接走后面的

permission_dict = request.session.get(settings.PERMISSION_URL_DICT_KEY)

#在初始化的时候把url以字典的显示存在了session里面,现在获取的也就是一个字典了

# print("==========",permission_dict)

flag = False

for group_id,code_url in permission_dict.items():

for url in code_url["urls"]:

regax = "^{0}$".format(url)

# print(regax,current_url)

if re.match(regax,current_url):

#match只要是..开头的都能匹配到,多以的加个^和$符

request.permission_code_list=code_url["codes"]

flag = True

break

if flag: #跳出外层循环

break

if not flag:

return HttpResponse("无权访问")

def process_response(self,request,response):

return response

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值