伙伴云客服论坛»论坛 S区 S客户管理 查看内容

0 评论

0 收藏

分享

RBAC权限管理

目录
用户权限
权限框架
1.RBAC介绍
RBAC概述
RBAC生命周期
2. RBAC表
模型类定义
3. RBAC中间件管理
自定义路由中间件
用户权限

一个商城,后台维护人员不只一个,还有其他后台人员,如:信息录入、财务、运营、采购等,他们对应的角色不同,所对应的权限也不相同,需要后台管理员来分配权限。
权限框架

RBAC模型5大属性,分别是: 1 用户属性(张三、李四、王五) 2 角色属性(销售经理、销售、前台) 3 用户与角色的关系(张三 是 销售经理 、李四 王五 是 销售) 4 权限(添加客户、编辑客户、删除客户,查看客户) 5 权限与角色的关系(销售 拥有 查看客户的 权 限、销售经理可以 查看/添加/删除/编辑客户的)
一个RBAC权限模块,必然要实现三个功能 用户管理 用户列表 添加用户 编辑用户 设置用户角色 角色管理 角色列表 添加角色 编辑角色 设置角色权限 权限管理 权限列表 新增权限 编辑权限
1.RBAC介绍

RBAC概述

在网站中,用户通过URL地址,进入网站的后端逻辑,从而对网站的数据库停止操作管理。可以让拥有权限的用户来完成操作,而没有权限的用户无法操作.
RBAC是基于角色的访问控制(Role-Based Access Control ),在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限,这就极大地简化了权限的管理。将权限赋予角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
RBAC认为受权实际上是Who 、What 、How 三元组之间的关系,也就是Who 对What 停止How 的操作,也就是“主体”对“客体”的操作。
Who:是权限的拥有者或主体(如:User,Role)。
What:是操作或对象(operation,object)。
How:详细的权限(Privilege,正向受权与负向受权)。
RBAC生命周期

1、用户登陆验证
2、根据用户身份验证信息,获取用户的角色---所有
3、通过用户所绑定的角色,获取这个角色绑定的所有权限,并去重----存储session/ redis
4、查询用户所==访问的URL==是否在角色的权限内,假设在,则继续访问,假设不在,回绝访问
2. RBAC表

模型类定义
  1. from django.db import models
  2. from django.contrib.auth.models import AbstractUser
  3. # 权限类型(角色)
  4. # name varchar(30)  '权限类型的名称'
  5. class PermissionType(models.Model):
  6.     """权限的类型"""
  7.     name = models.CharField(max_length=30, verbose_name='权限类型的名称')
  8.     class Meta:
  9.         db_table = 'permission_type'
  10.     def __str__(self):
  11.         return self.name
  12. # 用户模型类,继承AbstractUser
  13. # phone, varchar(11) 允许空 唯一 '用户手机'
  14. # last_login
  15. # role  fk--->PermissionType
  16. class User(AbstractUser):
  17.     """
  18.     用户表
  19.     """
  20.     phone = models.CharField(max_length=11, null=True, unique=True, blank=True, verbose_name='用户手机')
  21.     last_login = models.DateTimeField()
  22.     # 已定义好的模型类,可添加字段
  23.     role = models.ManyToManyField(PermissionType, verbose_name='所属角色')
  24.     class Meta:
  25.         db_table = 'user'
  26.     def __str__(self):
  27.         return self.username
  28. # 权限表
  29. # name  varchar(30)  '权限名称'
  30. # code_name  varchar(300)  '权限识别名称'
  31. # type_name fk  --->PermissionType
  32. class Permission(models.Model):
  33.     """
  34.     权限模型类
  35.     """
  36.     name = models.CharField(max_length=30, verbose_name='权限名称')
  37.     code_name = models.CharField(max_length=300, verbose_name='权限识别名称')
  38.     type_name = models.ForeignKey(PermissionType, on_delete=models.CASCADE)
  39.    
  40.         def __str__(self):
  41.                 return self.name
  42.                
  43.     class Meta:
  44.         db_table = 'permission'
  45. # 用户组
  46. # name  varchar(30)  '组名称'
  47. # user  m:n
  48. # permission m:n
  49. class UserGroup(models.Model):
  50.     """用户组的模型类"""
  51.     name = models.CharField(max_length=30, verbose_name='组名称')
  52.     user = models.ManyToManyField(User)
  53.     # 更改模型类: 改为多对多
  54.     permission = models.ManyToManyField(Permission)
  55.     class Meta:
  56.         db_table = 'user_group'
  57.     def __str__(self):
  58.         return self.name
复制代码
3. RBAC中间件管理

自定义路由中间件
  1. from django.utils.deprecation import MiddlewareMixin
  2. from django.http import JsonResponse, HttpResponse
  3. from rest_framework_jwt.utils import jwt_decode_handler
  4. from jwt.exceptions import ExpiredSignatureError, DecodeError
  5. import re
  6. import redis
  7. import json
  8. # 我的权限控制中间件
  9. class MyRBAC(MiddlewareMixin):
  10.     def __init__(self, handler):
  11.         super(MyRBAC, self).__init__(handler)
  12.         self.redis_cli = redis.Redis(host="localhost", port=6379, password="laufing", db=3)
  13.     # 路由中间件
  14.     def process_request(self, request):
  15.         # 获取恳求的地址,不含查询参数, 以/开头
  16.         path = request.path_info[1:]
  17.         # 恳求的方法
  18.         method = request.method.lower()
  19.         # 判断是否 登录/管理员 的恳求
  20.         if re.findall(r"login|^admin", path, re.I):
  21.             # 继续向后走
  22.             return None
  23.         # 不是登录,则判断是否有会话坚持 cookie or session or jwt
  24.         # 这里简单一些,就对应前端项目的jwt token
  25.         payload = self.validate_token(request)
  26.         if payload:
  27.             # 有会话坚持
  28.             print("解析的用户payload:", payload)
  29.             # 检查用户是否有权限访问
  30.             # 获取当前用户的所有权限
  31.             permissions = self.redis_cli.get("user_permissions_%s"%payload.get("user_id"))
  32.             permissions_list = json.loads(permissions.decode())
  33.             print("当前用户的所有权限:", permissions_list)
  34.             # 判断 当前恳求的地址是否在权限列表
  35.             for permisson in permissions_list:
  36.                 # 判断恳求方法
  37.                 if permisson.startswith(method):
  38.                     # 获取路由的正则形式
  39.                     re_path_info = permisson.split()[1]
  40.                     if re.findall(re_path_info, path, re.I):
  41.                         # 具有权限,继续向后走
  42.                         return None
  43.             #print(path, method)
  44.             return JsonResponse({"msg": "无权限访问", "code": 403}, status=403)
  45.             #return HttpResponse(json.dumps({"msg": "正在检查...", "payload": payload}, ensure_ascii=False))
  46.         else:
  47.             return JsonResponse({"code": 401, "msg": "未认证"}, status=401)
  48.     @staticmethod
  49.     def validate_token(request):
  50.         # 获取jwt token
  51.         token = request.headers.get("Authorization")
  52.         if not token:
  53.             return False
  54.         # 解析token
  55.         token_ = token.split()[1]
  56.         try:
  57.             payload = jwt_decode_handler(token_)
  58.         except DecodeError:
  59.             return False
  60.         except ExpiredSignatureError:
  61.             return False
  62.         return payload
复制代码
注意:此时用户完成登录认证时,需要存储用户的所有权限
  1. # 获取当前用户的角色 集合
  2. roles = user.role.all()
  3. # 根据角色获取所有的权限  [(v1,), (v2,),.....]
  4. permissions_list = []
  5. for role in roles:
  6.      permissions = role.permission_set.all().values_list("code_name")
  7.      permissions_list += [i[0] for i in permissions]
  8. # 权限去重
  9. permissions_list = list(set(permissions_list))
  10. # 权限存入redis
  11. user_permissions = "user_permissions_%s"%user.id
  12. redis_cli.set(user_permissions, json.dumps(permissions_list))
  13. redis_cli.close()
  14. return Response({
  15.      "code": "200",
  16.      "msg": "登录胜利, 进入首页",
  17.      "token": token,
  18.      "user": user.username
  19. })
复制代码

回复

举报 使用道具

相关帖子
全部回复
暂无回帖,快来参与回复吧
本版积分规则 高级模式
B Color Image Link Quote Code Smilies

橘生淮南
注册会员
主题 13
回复 14
粉丝 0
|网站地图
快速回复 返回顶部 返回列表