drf从入门到精通---day10(drf-jwt源码执行流程,自定义用户表签发和认证,设置token过期时间,simpleui的使用,rbac权限控制,)
昨日回顾
# 1 接口文档的编写
-1 word,md 编写----》存放位置:存放共享文件平台,git上
-2 第三方的接口文档编写平台
-3 公司自己开发,使用开源搭建 yapi
-4 自动生成接口文档
-djagno+drf:swagger,coreapi
-FastAPI:自带自动生成接口文档
-接口文档应该有的东西
-接口描述
-请求地址
-请求方式
-请求编码格式
-请求参数(get请求参数,post,put请求参数)
-参数类型
-参数是否必填
-参数解释
-返回数据
-json格式示例
-重点参数解释
-错误码:写到全局
# 2 cookie,session,token发展历史
-会话保持
-cookie:存在于客户端浏览器的键值对
-session:存于服务端的键值对(可能存的位置:文件,内存,数据库。。。)会占用后端资源
-token:三部分:头,荷载,签名
-签发:登录
-认证:携带着token过来进行认证,确认无误,才能调用需登录后才能访问的接口
认证的代码可以写在的位置取决于你用的框架可能存在的位置:
-认证类
-中间件
-装饰器
-别的位置
# 3 jwt:json web token :前后端认证的机制,token的web形式认证机制
----------------------------------
# 4 base64
-jwt
-前后端交互:字符串---》base64编码
-图片:使用base64编码
base64.b64encode(dic_str.encode('utf-8'))
# 字典先转json字符串,再转二进制后才能用base64编码
base64.b64decode('joYZgeFONFh7HgQ=')
----------------------------------
# 5 django+drf如何使用jwt
-drf-jwt
----------------------------------
# 6 快速签发
-配置一条路由----》帮咱们写了登录接口
----------------------------------
# 7 定制返回格式
-写一个函数要定义3个行参 token,User=None,request=None
返回什么,前端就看到什么
-配置文件中配置
----------------------------------
# 8 jwt 的认证
-局部:视图类上
-认证类 ---》JSONWebTokenAuthentication
-权限类:drf IsAuthenticated
-全局
-携带token
-请求头中
Authorization:jwt sadsfasdfasdf.asdfasdf.asdfasdf
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
----------------------------------
# jwt 配置问题
-记住的 # token过期时间
-JWT_RESPONSE_PAYLOAD_HANDLER
-'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
# 一般过期时间设7天
-了解的
'JWT_AUTH_HEADER_PREFIX': 'JWT', # 认证头前缀!这也是为什么
'JWT_SECRET_KEY': settings.SECRET_KEY, # 密钥
.
这个密钥是一开始创项目的时候,自动随机生成的!
.
还可以从rest_framework_jwt文件里面的settings里面将'JWT_SECRET_KEY': settings.SECRET_KEY,这行话可以直接放到项目的配置文件里面去
.
.
.
.
.
.
今日内容
1 drf-jwt源码执行流程(了解,读懂就可以自己封装一个jwt了)
1.1 补充
#1 django 的auth user表,密码是加密的,即便的同样的密码,密文都不一样
-每次加密,都会随机生成一个盐
-------------------------------------
# 比如 auth表中的用户密码为
pbkdf2_sha256$260000$B9ZRmPFpWb3H4kdDDmgYA9$CM3Q/ZfYyXzxwvjZ+HOcdovaJS7681kDsW77hr5fo5o=
pbkdf2_sha256 加密方式
260000 固定数字
B9ZRmPFpWb3H4kdDDmgYA9 随机生成的盐
CM3Q/ZfYyXzxwvjZ+HOcdovaJS7681kDsW77hr5fo5o=
这个是用注册的密码和盐拼在一起然后用加密算法生成的字符串
当登录的时候,用户提交用户名与密码过来后,从数据库表里面拿出该用户的盐与登录的密码
合在一起,然后用加密算法再生成字符串,然后比较生成的字符串 与 数据库里面的该字符串
CM3Q/ZfYyXzxwvjZ+HOcdovaJS7681kDsW77hr5fo5o= 进行比较对了就确认用户密码输入正确
----------------------------------------
#2 自定义用户表,生成密码用密文
django 里面自带了一个函数make_password ,往函数括号里面传个明文,会自动生成一个密文
from django.contrib.auth.hashers import make_password
res = make_password('teng123') # 就会自动加密了
要在项目启动起来,该代码才能正常执行
项目没启动起来的情况下, 用到django的东西得在测试环境,才能运行!!!
.
.
.
.
1.2 jwt如何自动完成token签发(自动登录)
# 登录接口,post请求,路由匹配成功,执行obtain_jwt_token-----
# obtain_jwt_token = ObtainJSONWebToken.as_view()
# -----最终执行的是ObtainJSONWebToken的post方法
path('login/', obtain_jwt_token),
# ObtainJSONWebToken类继承了JSONWebTokenAPIView
class ObtainJSONWebToken(JSONWebTokenAPIView):
serializer_class = JSONWebTokenSerializer
# JSONWebTokenAPIView类继承了APIView,
# JSONWebTokenAPIView里有post方法
def post(self, request, *args, **kwargs):
# 实例化得到序列化类的对象,就是JSONWebTokenSerializer(data=request.data)产生对象
serializer = self.get_serializer(data=request.data)
# 做校验:字段自己,局部钩子,全局钩子
if serializer.is_valid():
# user:获取全局钩子函数运行的返回结果里面的 当前登录用户
user = serializer.object.get('user') or request.user
# 同理获取签发的token
token = serializer.object.get('token')
# 构造返回格式,咱们可以自己定制,就是上节课讲的我们写在utils.py里面的函数!!
response_data = jwt_response_payload_handler(token, user, request)
response = Response(response_data)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
token,
expires=expiration,
httponly=True)
# 如果我们在jwt的配置文件里面把'JWT_AUTH_COOKIE'设置成True,就会走if里面的代码
# 作用就是前后端混合也能用,走这里就会把token往cookie里面写
# 我们现在前后端分离,后端正常是把token也放在字典里面用Response返回给前端,前端从响应体里面拿token
#最终返回了咱们定制的返回格式
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
.
.
.
.
.
1.3 jwt如何自动完成token签发(自动登录) 如何得到user
# 如何得到user,如何签发的token----》在序列化类的全局钩子中得到的user和签发的token !!
# 也就是说在执行serializer.is_valid()的时候,就会执行全局钩子函数validate
# JSONWebTokenSerializer序列化类---全局钩子---validate
# if serializer.is_valid():就会执行JSONWebTokenSerializer里面的validate函数,为什么?
# 因为JSONWebTokenSerializer最终继承的是BaseSerializer所以走该类里面的is_valid函数
# 该类里面的is_valid函数函数里面走全局钩子validate函数
# 但是JSONWebTokenSerializer也有validate函数,所以就会运行JSONWebTokenSerializer
# 里面的validate函数
def validate(self, attrs):
# attrs 就是前端传入,校验过后的数据--{"username":"lqz","password":"lqz1e2345"}
credentials = {
# self.username_field: attrs.get(self.username_field),
'username':attrs.get('username')
'password': attrs.get('password')
}
if all(credentials.values()):
# 如果credentials字典里面的两个键对应的值都有值,就可以继续往下走
# auth 模块,authenticate方法 可以传入用户名,密码
# 如果用户存在,就返回当前登录的用户对象,如果不存就是None
# 这行代码,这也是为什么jwt能自动完成登录确认的原因!!!
user = authenticate(**credentials)
if user:
# 校验用户是否是活跃用户,如果禁用了,也不能登录成功
if not user.is_active:
msg = _('User account is disabled.')
raise serializers.ValidationError(msg)
# 重要---通过user得到荷载 {id,name,email,exp}
payload = jwt_payload_handler(user) # 重点代码
return {
# 重点代码 jwt_encode_handler函数通过荷载就能得到token串
'token': jwt_encode_handler(payload),
'user': user }
else:
msg = _('Unable to log in with provided credentials.')
raise serializers.ValidationError(msg)
else:
msg = _('Must include "{username_field}" and "password".')
msg = msg.format(username_field=self.username_field)
raise serializers.ValidationError(msg)
-----------------------------------------
-----------------------------------------
### 重点代码!!!!:
1 利用django的authenticate模块,通过authenticate()方法,根据传过来的用户名与密码拿到当前登录用户对象user
2 通过用户名与密码去数据库查询出对象 user = authenticate(**credentials)
3 通过user对象得到荷载:payload = jwt_payload_handler(user)
4 通过荷载签发token:jwt_encode_handler(payload)
-----------------------------------------
-----------------------------------------
## 了解:
# 翻译函数,只要做了国际化,放的英文,会翻译成该国语言(配置文件配置的)
from django.utils.translation import ugettext as _
msg = _('Unable to log in with provided credentials.')
-----------------------------------------
.
.
通过user_obj对象生成payload
from rest_framework_jwt.utils import jwt_payload_handler
.
通过payload生成token串
from rest_framework_jwt.utils import jwt_encode_handler
.
.
.
.
.
1.4 jwt自带的认证类源码分析(JSONWebTokenAuthentication认证类)
# JSONWebTokenAuthentication---->父类BaseJSONWebTokenAuthentication----》
# authenticate方法
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
def authenticate(self, request):
# 获取前端带在请求头中的token值 这个代码很重要
jwt_value = self.get_jwt_value(request)
# 如果没有携带token,就不校验了!!所以才要配合drf的登录的权限类,来确认是否携带token
if jwt_value is None:
return None
try:
payload = jwt_decode_handler(jwt_value) # 重点代码
# jwt_value就是token
# 通过token,得到荷载,得到荷载的过程中可能会出错!!!
# 出错的原因:用户篡改token串,token过期了,未知错误
except jwt.ExpiredSignature:
msg = _('Signature has expired.') # 过期了
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.') # token串有问题导致解出来的签名不一样
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
# 如果能顺利解开,没有被异常捕获,说明token是可以信任的
# payload就可以使用,通过payload得到当前登录用户对象
user = self.authenticate_credentials(payload)
# 返回当前登录用户,token
return (user, jwt_value)
----------------------------
# 获取前端带在请求头中的token 值
# jwt_value = self.get_jwt_value(request)
# get_jwt_value函数在JSONWebTokenAuthentication类里面
def get_jwt_value(self, request):
# get_authorization_header函数作用获取前端请求头中传入的 jwt token串
# 按空格切割再解压赋值的列表 auth=['jwt','token串']
auth = get_authorization_header(request).split()
# 获取jwt的配置文件里面的认证头前缀转小写,实际上就是'jwt'
auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
if not auth:
# 请求头中如果没带,去cookie中取
if api_settings.JWT_AUTH_COOKIE:
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
return None
# 如果前端传的不是jwt,直接返回空!!!
if smart_text(auth[0].lower()) != auth_header_prefix:
return None
if len(auth) == 1: # 列表里一个值不行
msg = _('Invalid Authorization header. No credentials provided.')
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2: # 列表里两个值以上也不行
msg = _('Invalid Authorization header. Credentials string '
'should not contain spaces.')
raise exceptions.AuthenticationFailed(msg)
return auth[1] # 最终返回token值
-------------------------------------------
-------------------------------------------
jwt认证类代码总结:
# 当给接口函数配置了jwt自带的JSONWebTokenAuthentication认证类后,
# 如果不是 jwt空格token串 或者jwt空格token串里面jwt三个字母写错 ,都不会校验,
# 所以一定配合权限类使用permission_classes = [IsAuthenticated]
# 所以如果不带这个权限类进行限制,用户不带token就能直接继续运行视图类的相关方法的。
----------------------
# JSONWebTokenAuthentication 这个是jwt自带的认证类
# 该类里面有get_jwt_value函数,该类的父类里面有authenticate方法又调用get_jwt_value
# 最后的返回值就是get_jwt_value里面就是按Authorization键拿到jwt空格token串,
# 然后再split按空格切开,才拿到token串
# 所以要是用该认证类在请求头里面携带的token所对应的键就一定要是Authorization,值一定要先jwt空格再接token串的原因!!!
.
要对视图类的接口函数配jwt自带的登录认证类,有一个前提,
用户表是继承auth表的,如果自己写的用户表的时候,用不了jwt自带的登录认证类
原因是,用playload解析出user对象的时候,解析不出来,只有继承或用了auth表,才能解析出来
所以
.
.
这也是为什么没继承auth表,自己写的用户表,加了jwt自带的登录认证类后,虽然请求头里面
携带了jwt token串,显示无效签名的原因!!!
解决办法,自己重写认证类,别用jwt自带的登录认证类了!!!
.
.
.
.
2 自定义用户表进行签发和认证( 重要!!! )
也就是不用jwt自带的快速签发功能,自己写登录接口函数,不用jwt自带的认证类,自己写认证类
.
.
2.1 自定义用户表签发(登录接口)
代码示范
视图层
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from app01.models import Userinfo
from rest_framework.response import Response
from rest_framework_jwt.settings import api_settings # 导入jwt的配置文件
# JSONWebTokenSerializer类的上面复制过来的
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
from django.contrib import auth
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user_obj = Userinfo.objects.filter(username=username, password=password).first()
# user_obj = user_obj = auth.authenticate(request, username=username, password=password)
# 注意如果用的或继承的auth_user表,注册在里面的密码是被加过密的,所以直接用密码的明文
# 去表里面查是查不出用户对象的,authenticate方法有自动加密并查询的功能
if user_obj:
# 自己签发token,通过user_obj 得到payload
payload = jwt_payload_handler(user_obj)
# 自己通过payload 得到token
token = jwt_encode_handler(payload)
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
# 就是自己写登录接口函数,自己用前端的用户名与密码去数据库了查出对象,
# 确认密码账号没有问题,并拿到对象,自己通过对象的到荷载,通过荷载签发token,最后自己返回给前端
# 要是用jwt的快速签发功能,jwt封装的代码帮你全干了!!
.
.
.
.
2.2 自定义用户表认证
代码示范
视图层
from app01.authentication import JsonWebTokenAuthentication
class TestView(ViewSet):
authentication_classes = [JsonWebTokenAuthentication]
@action(methods=['GET'], detail=False)
def test(self, request):
return Response('ok')
------------------------------------
# 这是我们自己写的自定义的认证类,就是抄的的jwt自带的认证类JSONWebTokenAuthentication
# from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
import jwt
from rest_framework_jwt.utils import jwt_decode_handler
from app01.models import Userinfo
#
class JsonWebTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
# 取出token
token = request.META.get('HTTP_TOKEN')
if token:
try:
payload = jwt_decode_handler(token) # 重点代码 用token获取荷载
user_obj = Userinfo.objects.get(pk=payload.get('user_id'))
# 得到当前用户对象,get是filter与first的结合,但是如果拿不到直接报错,说明荷载有问题
# 只要访问一次登录接口,就会去Userinfo表中查一次用户---优化操作
# user_obj = Userinfo(id=payload.get('user_id'),username=payload.get('username'))
# 或者user_obj={'id':payload.get('user_id')}
return token,user_obj
except jwt.ExpiredSignature:
raise AuthenticationFailed('token过期')
except jwt.DecodeError:
raise AuthenticationFailed('token认证失败')
except jwt.InvalidTokenError:
raise AuthenticationFailed('token无效')
except Exception as e:
raise AuthenticationFailed('未知错误')
raise AuthenticationFailed('token没有传,认证失败')
# 我们自己写了认证类,也写了authenticate方法,这样给接口函数配上后,
# 前端在请求头里面放token串时,键就是字符串token,值就是token串,不用再加jwt空格了!!
# 因为我们没有像jwt源码那么烦,我们直接按token取的,也没按空格切割取索引1这些操作,没有花里胡哨的操作,所以token串前不加jwt空格了
-------------------------------------
# 配置
import datetime
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # token过期时间
}
--------------------------------------
.
.
.
以下所有代码在,D:\pythonProject\drf_day09
.
.
3 simpleui的使用
# 之前公司里,做项目,要使用权限,要快速搭建后台管理
# 使用djagno的admin直接搭建,但django的admin界面不好看
---------------------------------------------
# 就有了第三方模块的美化:
-xadmin:作者弃坑了,基于bootstrap+jq写的
-simpleui:基于vue写的,界面更好看
--------------------------------------------
# 现在阶段,一般前后端分离比较多:后台一般是django+前端一般是vue
-带权限的前后端分离的快速开发框架
-django-vue-admin # 类似于django-vue-admin的框架 是很多公司内部系统的基础框架
-自己写
.
.
.
3.1 使用步骤
# simpleui官方文档,点击教程&指南 查看如何使用
https://simpleui.72wo.com/docs/simpleui/
-----------------------------------------------
# 1 安装
pip3.8 install django-simpleui
# 2 在app中注册一下!! 放在注册的app的列表里面的最上面
INSTALLED_APPS = [
'simpleui',
]
只要下载了模块,注册了,立马django的后台就变了
----------------------------------------
.
.
.
.
.
.
# 3 内部app,图书管理系统某个链接要展示的字段 要在项目的admin.py 中注册一下
# 自定义按钮
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('nid', 'name', 'price', 'publish_date', 'publish') # 多对多字段不能往括号里写
# Book表里面增加自定义按钮
actions = ['custom_button']
def custom_button(self, request, queryset):
# queryset 就是选的对象
print(queryset) # 点击该按钮就会触发函数代码的执行
custom_button.confirm = '你是否执意要点击这个按钮?'
# 点击按钮就会触发一个确认的弹窗,并显示对应的文本
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 = 'danger'
# 给按钮里面字体追加自定义的颜色
custom_button.style = 'color:black;'
想要展示表里面的多个字段
.
.
其他表同理也这样改改,英文就变成中文了,
这样快速的就有了一个后台的每一个表就有了增删查改功能了
.
.
actions里面的按钮要配合函数使用
queryset 就是选的对象,点击该按钮就会触发函数的执行
.
.
.
.
.
# 4 调整左侧导航栏 比如在左侧菜单栏再添加一个按钮怎么办?
------------------------
1. menu_display对应menus字典里面的name键对应的值
2. 如果是项目的app,就在menus字典里面注册一下app的名字
3. 菜单可以多级,一般咱们内部app,都是两级,比如图书管理是一级,下面的表是二级
4. 可以增加除咱们app外的其它链接---》如果是外部链接,直接写地址,
5. 如果是内部链接,跟之前前后端混合项目一样的写法,直接写路由
--------------------
粘贴到项目的配置文件里面
import time
SIMPLEUI_CONFIG = {
'system_keep': False,
# 一级菜单
'menu_display': ['图书管理', '权限认证', '张红测试'],
# 开启排序和过滤功能, 不填此字段为默认排序和全部显示,
# 空列表[] 为全部不显示.
'dynamic': True,
# 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
'menus': [
{ # 第1个按钮
'name': '图书管理',
'app': 'app01', # 注册一下项目名!!! 很重要!!!
'icon': 'fas fa-code', # fas fa-code对应的图标是 </>
# 二级菜单
'models': [
{
'name': '图书',
'icon': 'fa fa-user', # fa fa-user对应的图标是个小人头像图标
'url': 'app01/book/'},
{
'name': '出版社',
'icon': 'fa fa-user',
'url': 'app01/publisssh/'},
{
'name': '作者',
'icon': 'fa fa-user',
'url': 'app01/author/'},
{
'name': '作者详情',
'icon': 'fa fa-user',
'url': 'app01/authordetail/'},
] },
{ # 第2个按钮
'app': 'auth',
'name': '权限认证',
'icon': 'fas fa-user-shield', # 带盾牌的小人头像图标
# 二级菜单
'models': [
{
'name': '用户',
'icon': 'fa fa-user',
'url': 'auth/user/'},
{
'name': '组',
'icon': 'fa fa-user',
'url': 'auth/group/'},
]
},
{ # 第3个按钮
'name': '张红测试',
'icon': 'fa fa-file', # 文本的图标
'models': [
# 二级菜单
{ 'name': 'Baidu',
'icon': 'far fa-surprise',
# 第三级菜单
'models': [
{ 'name': '爱奇艺',
'icon': 'fa-solid fa-bug-slash',
'url': 'https://www.iqiyi.com/dianshiju/'
},
{ 'name': '百度问答',
'icon': 'fa-solid fa-filter',
'url': 'https://zhidao.baidu.com/'
}
]
},
# 二级菜单
{ 'name': '大屏展示',
'url': '/show/',
'icon': 'fab fa-github'}
] # 'models'对应的列表结尾
} # 'menus'对应的列表里面的最后一个字典结尾
] # 'menus'对应的列表结尾
} # SIMPLEUI_CONFIG 字典的结尾
# 图标怎么改,https://fontawesome.com/icons/bug-slash?s=solid 网站上去找
# 看到喜欢的图标,左键点击,进入后,class="样式类" 去复制样式类 有的有用,有的没用
----------------------
# 第四级就不支持了,element只支持了3级菜单!!!
# 注意url对应的路由是你自己写的,但是你只要用了simpleui的后台管理
# 后台管理会自动帮你生成路由项目名 admin/ app01/authordetail/ 这种项目加表名组合的路由
# 所以你写的路由要和自动生成的路由对应上,点对应的图标按钮才会跳到对应的表页面上去!!!
# 如果你想要一个按钮有一个不存在的路由,那么你要先去路由层注册一下
# 或者url可以对应一个存在的外部网页链接
模型表里面表建好,注册一下,再重新打开后台就变了
.
改左边项目的名字将app01改成中文
.
.
url对应的路由虽然是你自己写的,
但是一定要是已经存在的路由,你只要在django的项目的admin.py里面注册了模型表的表名,
并在settings里面注册了simpleui,simpleui会自动帮你生成路由这种
admin/ app01/authordetail/ 这种项目名加表名组合的路由
所以你写的路由要和自动生成的路由对应上,点对应的图标按钮才会跳到对应的表页面上去!!!
.
.
.
当想要写一些页面,这些页面又和表没有必然联系的时候,url对应的就要是我们项目中已经注册的路由了
要先退出一下,再登录再点大屏展示按钮,就会显示后端的视图函数render的html页面了
.
.
.
.
# 5.1 后台里面,将字段名字改成中文
-新增,查看修改展示中文,在表模型的字段上加:verbose_name='图书名字' 与
help_text='这里填图书名' 来控制中文的显示与提示
# 5.2 后台里面,将app名字改成中文
-app名字中文:apps.py---加个verbose_name = '图书管理系统'
---------------------------------------
---------------------------------------
.
.
.
# 6 其它配置项
SIMPLEUI_LOGIN_PARTICLES = False # 关闭登录页面动态效果
# 改登录页面的logo 原来的django图标就被替换掉了
SIMPLEUI_LOGO = 'https://avatars2.githubusercontent.com/u/13655483?s=60&v=4'
SIMPLEUI_HOME_INFO = False # 隐藏首页右上角的服务信息
SIMPLEUI_HOME_QUICK = False # 隐藏首页的快捷操作图标内容
SIMPLEUI_HOME_ACTION = False # 隐藏首页的最近动作
---------------------------------------
# SIMPLEUI_HOME_PAGE = 'https://https://www.cnblogs.com/' 不怎么好用 改首页配置
# SIMPLEUI_HOME_TITLE = '博客园首页' 不怎么好用 改首页标题
# SIMPLEUI_HOME_ICON = 'fa fa-user' 不怎么好用 改首页图标
这3个不太会用,要琢磨一下,怎么用
隐藏右上角的服务信息,配置文件里面再加一行代码
SIMPLEUI_HOME_INFO = False
.
.
SIMPLEUI_HOME_QUICK = False # 隐藏首页的快捷操作图标内容
SIMPLEUI_HOME_ACTION = False # 隐藏首页的最近动作
.
.
.
.
.
.
.
3.2 大屏展示
# 监控大屏展示 到gitee上面 https://gitee.com/
搜索展示大屏
--------------------------------
适用于前后端混合项目,js,css,图片对应好,就可以了
就是别人写的很好看的前端,我们抄过来,用模板语法做个替换,就可以了
----------------------------
----------------------------
注意一点,路由匹配的时候,如果路由的前面没有斜杠就会以当前所在的路由为基础往后匹配
如果路由的前面加了斜杠,就会从端口号后面开始匹配
打个比方
假如一个图片的路径是img/second_title.png 当前的页面的路由是index/
在该页面加载加载该图片的时候,图片的路径变成index/img/second_title.png
假如图片的路径是/img/second_title.png 当前的页面的路由是index/
在该页面加载加载该图片的时候,图片的路径还是/img/second_title.png
---------------------------------
.
下载下来后,用pycharm打开
.
.
找到好看的,复制文件,粘贴到我们自己的项目里面的static静态文件夹内
settings里面静态文件的路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
.
再把index.html页面复制到我们项目的templete里面去
.
然后urls.py 里面配个路由,写个视图函数,专门就render到index.html页面,
这样就能访问到该html页面了,但是没样式
.
因为里面的文件路径没改了,要改一下
href=" 改成 href="static/ src=" 改成 src="static/
json/ 改成 /static/json/ img/改成 /static/img/
.
就成这样了,当然页面里面的数据都不是写死了,后端都是可以传到前端替换的
.
.
最后想要把大屏监控的按钮,放到左边侧边栏,搞定了!!!
.
.
.
.
.
.
.
.
4 权限控制(acl,rbac)
# python的应用场合:公司内部项目要快速开发成形,而不讲究太高的执行效率的情况下!!!
# 公司内部项目 一般是基于角色的访问控制 rbac
rbac:是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,
权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。
这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,
而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
-----------------------
用户表:用户和角色多对多关系,一个用户可能有多个角色,一个角色也可能会被赋予多个用户!!!
-----------------------
角色表: 一个角色可能有多个权限----》
-开发角色:拉取代码,上传代码
-财务角色:开工资,招人,开除人
-----------------------
权限表:角色和权限也是是多对多,
一个角色可以有多个权限,一个权限也可以赋予给多个角色!!!
-拉取代码
-上传代码
-开工资
-招人
-开除人
补充: 权限表里面的权限不是直接和用户有关系的,而是把权限赋给角色
基于角色的访问控制的核心是角色,角色有什么权限,用户只要属于该角色就能拥有什么权限
换句话说就是把权限赋予角色,把角色赋予用户,从而间接的控制用户有什么权限了
-----------------------
# 通过5张表完成rbac控制:用户表,角色表,权限表, 用户角色中间表, 角色权限中间表
一个用户登录了,想要知道他的权限,首先要拿到他所有角色,然后根据这些角色拿到所拥有的权限
-----------------------
-----------------------
# 如果某个人,属于财务角色,但只想要拉取代码权限,不要上传代码权限,怎么办?
# 肯定不可能把 开发角色 赋予给他,开发角色一给他肯定就有上传代码的权限了!!!
# 通过6张表来实现权限控制
用户表,
角色表,
权限表,
用户角色中间表,
角色权限中间表
用户和权限中间表 # 直接把权限授给用户,也是多对多
# 一个用户可以有多个权限,一个权限也可以授给多个用户!!!
# 这样的话,用户登录,查看他的权限,先查他的角色,把角色有的权限拿出来,
# 再到用户和权限中间表,把与用户直接关联的权限拿出来,再合起来,就是该用户的所有权限了
# diango的admin后台管理就是基于这6张表来实现的权限认证!!!
# 这就是为什么公司的内部管理系统想快速搭建,就用django的admin,在基础上做二次开发
# 原因就是权限不用写了,只需要写功能就行了
-------------------------------------------------
-------------------------------------------------
-------------------------------------------------
# 互联网项目 一般是基于访问列表的控制 acl ,比较简单
acl:Access Control List 访问控制列表,权限放在列表中,
只要列表中有,就有该权限,列表中没有,就没有该权限!!
所以用户一登录,该用户的权限表就已经加载出来了!!!
-权限:权限表----》 发视频,评论,开直播
-用户表:用户和权限是一对多
张三:[发视频,]
李四:[发视频,评论,开直播]
-------------------------------------------------
.
.
4.1 基于django-admin实现权限控制的操作
# 演示了 django-admin 的权限控制
由超级管理员来操作权限的分配,首先给用户分配组(角色),
其次如果该用户需要一些特殊的权限,没有组满足,就可以单独给用户授予权限!!!
-授予用户某个组
-单独单独给用户授予权限
---------------------------
---------------------------
# django的admin就是基于auth写的
# django的auth--6张表
auth_user # 用户表
auth_group # 角色表,组表
auth_permission # 权限表
-----------
auth_user_groups # 用户和角色中间表
auth_group_permissions # 角色和权限中间表
-------------
auth_user_user_permissions # 用户和权限中间表
---------------------------
---------------------------
# java:若依
# go :gin-vue-admin
# python :django-vue-admin
先添加组
.
由于我们创的用户都是超级管理员,超级管理员是有所有权限的
所以要先把用户的超级管理员身份去掉,一去掉保存,数据库user表里超级管理员字段数据也对应改了
然后再给该用户分配组(就是角色) 这样该用户就只有该组的权限了!!!
.
.
可以看到,给用户分配了,只能看书与出版社组后,该用户就只能看了,不能增删改了!!!
而且左边侧边栏,只有两个权限对应的按钮了,其他按钮直接没了!!!
.
.
.
.
django后台英文转中文
django的一个中间件,加了,后台的英文就变中文了
'django.middleware.locale.LocaleMiddleware',
或者
django是支持修改语言环境的,改一下LANGUAGE_CODE = 'zh-hans',
整个django的系统语言环境全部变成汉文了
.
.
.
补充
#3 用户表的密码忘了怎么办
-新增一个用户,把它的密码复制过去
# 4 双token认证
.
.
.
.
.
.
.
作业
1 整理 jwt 签发,认证流程
2 自定义用户表,签发,认证
3 自定义用户表,使用make_password保存密码
4 simpleui 写个图书管理系统
5 演示一下admin 的rbac
----------------------
6 研究 python casbin 支持acl rbac,abac。。。。权限控制
7 双token认证
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY