1、RBAC模型
- RBAC模型(Role-Based Access Control:基于角色的访问控制)
- 就是用户通过角色与权限进行关联
- 简单的说,一个用户拥有若干角色,每个角色拥有若干权限
- 这样,就构成了**“用户-角色-权限”**的授权模型
- 在这种模型中,用户与角色之间,角色与权限之间,一般都是多对多关系
2、表设计
from django.db import models
from django.contrib.auth.models import AbstractUser
from utils.MyBaseModel import Base
# Create your models here.
# 角色表
class Role(models.Model):
name = models.CharField('角色名称', max_length=32, unique=True)
class Meta:
db_table = 'tb_role'
# AbstractUser是django用户组件里的用户模型类,继承以后对原来的模型类进行改写
# 用户表
class User(AbstractUser):
phone = models.CharField('手机号', max_length=20, null=True)
img = models.ImageField(max_length=256, null=True)
nick_name = models.CharField('昵称', max_length=20, null=True)
address = models.CharField('地址', max_length=255, null=True)
email = models.CharField('邮箱', max_length=255, null=True)
vip = models.ForeignKey(Vip, on_delete=models.SET_NULL, default=None, null=True)
vip_expiration = models.DateField('vip到期时间', blank=True, default=None, null=True)
roles = models.ManyToManyField(Role, related_name='users')
class Meta:
db_table = 'tb_user'
def __str__(self):
return self.username
# 权限表/访问接口表
class UrlInfo(models.Model):
url = models.CharField('url', max_length=20, null=True)
desc = models.CharField('描述', max_length=128, null=True)
roles = models.ManyToManyField(Role, related_name='urlsinfo')
class Meta:
db_table = 'tb_urls'
def __str__(self):
return self.url
3、自定义访问权限
############################ userapp/permission.py ##########
from rest_framework.permissions import BasePermission
from userapp.models import User, Role, UrlInfo
# 方法一
class SYLPermission(BasePermission):
message = '当前用户没有该权限进行访问'
def has_permission(self, request, view):
uid = request.user.id # 获取当前用户id
user_obj = User.objects.filter(id=uid).first()
# 查询该用户 拥有的 所有角色
user_role_obj = user_obj.roles.all()
print("该用户的所有角色:", user_role_obj)
url = request.path_info
method = request.method
print(url + method)
# 查询 当前访问的路径
url_obj = UrlInfo.objects.filter(url=url + method).first()
print("当前路由对应的url对象", url_obj)
if url_obj:
# 如果存在路径信息, 获取该路径对应的 所有角色
url_role_obj = user_obj.roles.all()
else:
# 不存在,即没有权限
return False
# 循环遍历该用户的所有角色
for i in user_role_obj:
# 判断该用户拥有的角色 是否 存在当前路径对应的角色中
if i in url_role_obj:
return True
return False
# 方法二
class SYLPermission2(BasePermission):
message = '当前用户没有该权限进行访问'
def has_permission(self, request, view):
uid = request.user.id # 获取当前用户id
user_obj = User.objects.filter(id=uid).first()
# 查询该用户 拥有的 所有角色
user_role_obj = user_obj.roles.all()
print("该用户的所有角色:", user_role_obj)
url = request.path_info # 获取当前访问的路径
method = request.method # 获取当前访问的路径的方法
request_url = url + method
print(request_url)
# 循环遍历该用户拥有的角色
for i in user_role_obj:
print(i)
# 通过当前角色 获取当前角色 i 可以访问的所有路径url信息
url_obj = i.urlsinfo.all()
# 循环遍历 所有路径
for j in url_obj:
# 判断当前访问的路径 是否在 路径信息中
if request_url == j.url:
return True
return False
4、接口测试
from rest_framework.viewsets import ModelViewSet
from courseapp import models, serializers
from userapp.permission import SYLPermission, SYLPermission2
class CourseTypeView(ModelViewSet):
queryset = models.CourseType.objects.all()
serializer_class = serializers.CourserTypeSer
permission_classes = [SYLPermission2]