权限控制
ACL-访问控制列表
1.ACL(访问控制列表)的权限控制:(针对互联网用户的产品)
用户表:
"""
id name password
1 zhangsan 123
"""
权限表:
"""
id user_id 权限
1 1 评论权限
2 1 发抖音权限
"""
张三:[评论权限,发抖音权限]
RBAC-基于角色的访问控制
1.RBAC(Role-Based Access Control)基于角色的访问控制:(针对于公司内部项目)
权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
2.应用
Django的 Auth组件 采用的认证规则就是RBAC
1.像专门做人员权限管理的系统(CRM系统)都是公司内部使用,所以数据量都在10w一下,一般效率要求也不是很高
2.用户量极大的常规项目,会分两种用户:前台用户(三大认证) 和 后台用户(BRAC来管理)
结论:没有特殊要求的Django项目可以直接采用Auth组件的权限六表,不需要自定义六个表,也不需要断开表关系,单表可能需要自定义User表
3.前后台权限控制
1.后台用户对各表操作,是后台项目完成的,我们可以直接借助admin后台项目(Django自带的)
2.后期也可以用xadmin框架来做后台用户权限管理
3.前台用户的权限管理如何处理
定义了一堆数据接口的视图类,不同的登录用户是否能访问这些视图类,能就代表有权限,不能就代表无权限
前台用户权限用drf框架的 三大认证
django中的的auth
1.django的auth其实就实现了基于角色的访问控制--->通过表控制的(6张)
1.auth_user :用户表,存用户信息
2.auth_group:组,角色,存放角色信息
3.auth_permission:权限,存放权限信息
# 分析:一个组(角色)中,有多个用户,一个用户,属于多种角色---->多对多
4.auth_user_groups:用户和组的多对多中间表
# 分析:一个组,可能有多个权限,一个权限,也可能属于多个组--->多对多
5.auth_group_permissions:组和权限的多对多中间件
# django,多了张表:auth_user_user_permissions
# 分析:一个用户,可以有多个权限,一个权限,可以分配个多个用户--->多对多
6.auth_user_user_permissions:用户和权限多对多中间表
django中,如何做权限控制
1.创建书籍表,用户表
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField()
email = models.CharField(max_length=64)
class Meta:
verbose_name_plural = '用户表'
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=64)
class Meta:
verbose_name_plural = '书籍表'
def __str__(self):
return self.name
2.在管理员中注册
from django.contrib import admin
from .models import Book
admin.site.register(Book)
3.通过登陆django自己提供的后台管理系统,对书籍用户进行增删改,使得不同的用户,可以拥有不同的角色和权限
开发中做权限控制
1.基于python开发,公司内部项目用的多-->使用基于角色的访问控制的权限比较多
2.python+django 开发出一套公司内部项目,要带rbac的权限控制
1.基于django的auth+admin快速开发,有更多操作,但是没学
2.基于django的auth+admin+第三方美化快速开发
国内的:simple-ui,xadmin(弃用了)
3.基于django+vue+自定制权限
djagno-vue-admin :第三方开源
4.完全自己写
基于django的auth+admin+第三方美化快速开发
准备
1.安装:pip3 install django-simpleui
2.将simpleui注册--修改默认后台模板为simpleui
INSTALLED_APPS = [
'simpleui',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework'
]
详细教程:https://simpleui.72wo.com/docs/simpleui/quick.html#%E7%9B%AE%E5%BD%95
主题
1.默认主题:默认主题在settings.py中进行配置
# 指定simpleui默认的主题,指定一个文件名,相对路径就从simpleui的theme目录读取
SIMPLEUI_DEFAULT_THEME = 'admin.lte.css'
2.也可以在后台选择主题
图标
1.simpleui中显示的图标,可以在https://fontawesome.com/icons?d=gallery中查找
2.默认图标:simpleui对所有菜单提供了一个默认的file图标,是为了统一风格。也许你并不喜欢,你可以选择关闭默认图标
SIMPLEUI_DEFAULT_ICON = False # 关闭默认图标
3.自定义图标:simpleui仅为系统默认模块提供了图标,如果要为其他模块指定图标,可以自定义配置。图标参考请查阅:图标说明 优先级: 自定义->系统配图->默认图标
key:模块名字,请注意不是model的命名,而是菜单栏上显示的文本,因为model是可以重复的,会导致无法区分
vlaue 图标
eg:
SIMPLEUI_ICON = {
'系统管理': 'fab fa-apple',
'员工管理': 'fas fa-user-tie'
}
菜单
1.name:菜单名
2.icon:图标,参考element-ui和fontawesome图标
3.url:链接地址,绝对或者相对,如果存在models字段,将忽略url
4.models:子菜单,自2021.02.01+版本 支持最多3级菜单,使用方法可以看下方例子
5.newTab:boolean,default:False,浏览器新标签中打开,自2022.6.13开始支持
import time
SIMPLEUI_CONFIG = {
'system_keep': False,
'menu_display': ['我的地盘', '权限认证', '多级菜单测试', '动态菜单测试', '图书管理'], # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
'dynamic': True, # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
'menus': [
{
'name': '我的地盘',
'icon': 'fas fa-code',
'url': '/https://gitee.com/tompeppa/simpleui/',
# 浏览器新标签中打开
# 'newTab': True,
},
{
'app': 'auth',
'name': '权限认证',
'icon': 'fas fa-user-shield',
'models': [{
'name': '用户',
'icon': 'fa fa-user',
'url': 'auth/user/'
}]
},
{
# 自2021.02.01+ 支持多级菜单,models 为子菜单名
'name': '多级菜单测试',
'icon': 'fa fa-file',
# 二级菜单
'models': [
{
'name': 'Baidu',
'icon': 'far fa-surprise',
# 第三级菜单 ,
'models': [
{
'name': '爱奇艺',
'url': 'https://www.iqiyi.com/dianshiju/'
# 第四级就不支持了,element只支持了3级
},
{
'name': '百度问答',
'icon': 'far fa-surprise',
'url': 'https://zhidao.baidu.com/'
}
]
},
{
'name': '内网穿透',
'url': 'https://www.wezoz.com',
'icon': 'fab fa-github'
}]
},
{
'name': '动态菜单测试',
'icon': 'fa fa-desktop',
'models': [{
'name': time.time(),
'url': 'http://baidu.com',
'icon': 'far fa-surprise'
}]
},
{
'app': 'app01',
'name': '图书管理',
'icon': 'fas fa-user-shield',
'models': [
{
'name': '书本管理',
'icon': 'fa fa-user',
'url': 'app01/book/'
},
{
'name': '出版社管理',
'icon': 'fa fa-user',
'url': 'app01/publish/'
},
]
},
]
}
自定义按钮&Action
1.django admin 默认提供了自定义按钮的支持,但是样式、图标均不可自定义,simpleui在django admin 自定义action的基础上增加了样式、图标、按钮类型自定义。
@admin.register(Book)
class EmployeAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'price') # 列表页面,展示的字段
# 增加自定义按钮
actions = [ 'custom_button']
def custom_button(self, request, queryset):
print(request)
print(queryset)
# 显示的文本,与django admin一致
custom_button.short_description = '测试按钮'
# icon,参考element-ui icon与https://fontawesome.com
custom_button.icon = 'fas fa-audio-description'
# 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
custom_button.type = 'success'
# 给按钮追加自定义的颜色
custom_button.style = 'color:black;'
def make_copy(self, request, queryset):
pass
make_copy.short_description = '复制员工'
还有:其他相关配置
djagno-vue-admin演示
https://gitee.com/liqianglog/django-vue-admin
作业
1.多方式登录接口
使用auth的user表扩写
用户名+密码
手机号+密码
邮箱+密码
签发token逻辑,放在序列化类中写
views.py
from rest_framework.viewsets import ViewSet
from .serializer import UserSerializer
from rest_framework.response import Response
class LoginView(ViewSet):
def login(self,request):
# 获取用户名/手机号/邮箱 密码
ser = UserSerializer(data = request.data)
if ser.is_valid():
print(ser)
token =ser.save_user(ser.validated_data)
return Response({'code':100,'msg':'登陆成功','token':token})
else:
return Response({'code': 101, 'msg': '登陆失败', 'erros':ser.errors})
serializer.py
from .models import User
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['info','password']
info = serializers.CharField()
def _generate_token(self,user):
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
print(token)
return token
def validate(self, attrs):
username =None
email = None
phone = None
user_info = attrs.get('info')
password = attrs.get('password')
# 手机号 用户名 邮箱
if user_info.isdigit():
phone = attrs.get('info')
print(phone)
elif '@'in user_info:
email = attrs.get('info')
print(email)
else:
username = attrs.get('info')
print(username)
# 查找用户
if phone:
user = User.objects.filter(phone=phone,password=password).first()
if email:
user = User.objects.filter(email=email,password=password).first()
if username:
user = User.objects.filter(username=username,password=password).first()
if not user:
raise ValidationError('用户不存在')
attrs['user'] = user
return attrs
def save_user(self, validated_data):
user = validated_data['user']
token = self._generate_token(user)
return token