今日内容概要
- RBAC
- 自动生成接口文档
- jwt介绍与快速使用
- jwt定制返回格式
- jwt源码分析
内容详细
1、RBAC(重要)
在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
普通注册用户,VIP用户,超级VIP --》优酷,网易云音乐,百度网盘
公司内有部门(开发部,运维部,市场部,总裁办,人力资源部门)
权限和角色(部门)绑定
举个例子:发工资权限,招人权限,开发代码权限...
招人权限,发工资权限给人力资源
开发代码权限给开发部门
"""
python用来做公司内部项目居多:
人事系统,进销存,报销审批,自动化运维
原因:
公司内部项目对执行效率要求不高(人少)
对开发效率要求高(越快开发出越好,成本越低越好)
知乎,豆瓣用python写的---》随着用户量增大---》切换语言
"""
django-vue-admin:后端用drf,前端用vue,权限管理的 脚手架---》前后端分离
django的admin---》混合的后台管理用的多---》基于django的admin二次开发
simpleui:对django admin的美化
用户表
角色表(组表,部门表)
权限表
角色和权限 >>> 多对多中间表
用户和角色 >>> 多对多中间表
django-admin中多了一张表:
用户对权限 >>> 多对多中间表
"""
在关系型数据库的关系中:只有三种---》本质只有一种:外键关系
一对多
多对多
一对一
"""
1、纯基于原生
2、使用第三方美化:
xadmin(早就不维护了,弃坑了)
simpleui(国内的,主流),国外也有很多

django-admin演示
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
author = models.CharField(max_length=32)
def __str__(self):
return self.name
class Meta:
verbose_name = '图书表'
verbose_name_plural = '图书表'
from django.contrib import admin
from .models import Book
class BookAdmin(admin.ModelAdmin):
list_display = ('name', 'author', 'price')
list_filter = ('name', 'price', )
admin.site.register(Book, BookAdmin)
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False


2、自动生成接口文档
在公司里,前端和后端是两拨人写---》咱们后端接口写好了,我们知道接口怎么用
第一种:使用word或者md文档编写---》纯手写---》好的公司这么用
第二种:第三方平台录入---》半手写
https://blog.csdn.net/weixin_44337261/article/details/121005675-->部分公司
第三种:公司自己开发接口平台,搭建接口平台--》数据放在公司自己--》学长公司在用
https://zhuanlan.zhihu.com/p/366025001
第四种:自动生成接口文档---》用的少---》自动生成+导出---》录入到yapi
drf中有两个模块:coreapi,swagger
第一步:下载
pip3 install coreapi
第二步:修改路由
from rest_framework.documentation import include_docs_urls
router.register('books2', views.BookListCreateView, 'books2')
urlpatterns = [
...
path('docs/', include_docs_urls(title='站点页面标题')),
]
第三步:写视图类,只需要加注释即可
from rest_framework.generics import ListCreateAPIView
class BookListCreateView(ViewSetMixin, ListCreateAPIView):
serializer_class = BookSerializer
queryset = Book.objects.all()
"""
get:
返回所有图书信息.
post:
新建图书.
"""
from rest_framework import mixins
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
"""
list:
返回图书列表数据
retrieve:
返回图书详情数据
latest:
返回最新的图书数据
read:
修改图书的阅读量
"""
第四步:配置文件中
REST_FRAMEWORK = {
...
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}

3、jwt介绍和快速使用
https://www.cnblogs.com/liuqingzheng/articles/8990027.html
之前使用的django-session:
如果登录用户很多,需要在后端存很多数据,频繁查询数据库,导致效率低
能不能想一种方案,不在服务端存数据 在客户端存数据(数据安全)---》token认证机制
三段式---每一段都使用 base64编码
典型的jwt串样子,通过. 分隔成三段:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
第一段:头:声明类型,这里是jwt,声明加密的算法,公司信息等等(目前作用不大)
第二段:荷载(payload):有效信息
用户名,用户id,登陆时间,token失效时间...
第三段:签名(signature):通过 头+荷载 使用某种加密方式加密后得到的
登陆过程 如果没有第三方模块帮助我们做,我们就自己做
1)用基本信息公司信息存储json字典,采用base64算法得到 头字符串
2)用关键信息存储json字典,采用base64算法得到 荷载字符串,过期时间,用户id,用户名
3)用头、体加密字符串通过加密算法+秘钥加密得到 签名字符串 拼接成token返回给前台
访问需要登陆的接口
1)将token按 . 拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
2)第二段 体加密字符串,要反解出用户主键,通过主键从User表中就能得到登录用户,过期时间是安全信息,确保token没过期
3)再用 第一段 + 第二段 + 加密方式和秘钥得到一个加密串,与第三段 签名字符串 进行比较,通过后才能代表第二段校验得到的user对象就是合法的登录用户
django中有一个django-rest-framework-jwt,咱们讲的:
https://github.com/jpadilla/django-rest-framework-jwt
django中还有一个,django-rest-framework-simplejwt,咱们不讲,公司可能会用:
https://github.com/jazzband/djangorestframework-simplejwt
https://blog.csdn.net/lady_killer9/article/details/103075076
3.1、base64编码和解码
只是编码和解码,不能叫加密
import base64
对网络传输中的数据进行编码---->jwt,有些图片,使用base64编码(12306)
3.2、django中快速使用jwt
3.2.1、签发
pip3 install djangorestframework-jwt
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token),
]
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InB5eSIsImV4cCI6MTY0OTMxNjc3MiwiZW1haWwiOiIzMDYzMzQ2NzhAcXEuY29tIn0.YOUc9gcFIQf9FBibZJANaI3Rmpw4zfMy1e8ez1roKSI"
}
爬虫就是干这事,扣除token串,模拟发请求----》如果你能想一种方式,避免别人获取了token串,不能发请求---》你就把整个爬虫行业干掉了
3.2.2、认证
写认证类-->我们用了第三方模块---》第三方模块写了一个认证类
在视图类中配置:认证类+权限类
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class BookView(GenericViewSet, ListModelMixin):
'''
返回所有图书信息
'''
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [SearchFilter]
search_fields = ['name', 'author']
pagination_class = CommonCursorPagination
authentication_classes = [JSONWebTokenAuthentication, ]
permission_classes = [IsAuthenticated, ]
token携带方式:在请求头中使用 Authorization : jwt token串
为什么要按这个格式?
人家的认证类已经写完了,就是去请求头中取的,按固定规则取的,所以咱们需要按照这个格式
4、jwt定制返回格式
{code:100,msg:登陆成功,token:adfadf,username:pyy}
第一步:写一个函数(新建 utils.py文件)--->返回什么格式,前端就能看到什么格式
def jwt_response_payload_handler(token, user=None, request=None):
return {
'code': 100,
'msg': "登陆成功",
'token': token,
'username': user.username
}
第二步:在配置文件中配置(不配置就会使用 JWT默认的格式)
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',
}

5、jwt源码分析
obtain_jwt_token---》ObtainJSONWebToken.as_view():视图类.as_view()
ObtainJSONWebToken视图类---》登陆post请求,携带用户名密码---》视图类中有post方法
serializer_class = JSONWebTokenSerializer---》全局钩子中获取当前登录用户和签发token
serializer = self.get_serializer(data=request.data)
obtain_jwt_token---》ObtainJSONWebToken视图类---》post方法--》通过前端传入的用户名和密码拿到了当前用户,通过当前用户签发了token---》返回给了前端
认证类---》authenticate方法---》验证
def authenticate(self, request):
jwt_value = self.get_jwt_value(request)
if jwt_value is None:
return None
try:
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
user = self.authenticate_credentials(payload)
return (user, jwt_value)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)