一、基于自定义表编写认证类
认证类:
auth.py:
# 写一个类继承BaseAuthentication,重写authenticate方法 from rest_framework.authentication import BaseAuthentication from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework.exceptions import AuthenticationFailed from rest_framework_jwt.settings import api_settings import jwt jwt_decode_handler = api_settings.JWT_DECODE_HANDLER jwt_get_username_from_payload_handler = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER from .models import User class JwtAuthentication(BaseAuthentication): # 重写authenticate方法 def authenticate(self, request): # 获取前端传入的token进行验证,从请求头中获取token token = request.META.get('HTTP_TOKEN') # django——jwt 提供了校验token的方法,从这个JSONWebTokenAuthentication这个中找 try: # jwt提供的方法,进行token的校验 payload = jwt_decode_handler(token) # 传入token进行校验,校验通过返回payload,校验失败抛异常 # 通过payload 得到当前用户 # 认证类,配好后,只要有认证的,都会走这里---》每次走这里都会查询一次数据库 # 做个优化? # 1 自己根据payload数据,创建一个用户,有的参数没传,会使用默认值,跟我真实用户还是有区别的 # user=User(id=payload.get('user_id'),username=payload.get('username')) # 2 直接返回用户id,后续 的request.user 都是用户id,如果真正要用的时候,再查 user = User.objects.get(pk=payload.get('user_id')) except jwt.ExpiredSignature: # msg = _('Signature has expired.') # _是个函数的别名,这个函数是翻译函数,只要做了国际化,它就是中文 msg = '签名过期' raise AuthenticationFailed(msg) except jwt.DecodeError: msg = 'token错误' raise AuthenticationFailed(msg) except jwt.InvalidTokenError: msg = 'token不合法' raise AuthenticationFailed(msg) except Exception: raise AuthenticationFailed('未知错误,请联系系统管理员') return (user, token) # 后续的request.user 都是用户id,
登录接口:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework_jwt.settings import api_settings # drf的配置文件# from rest_framework_jwt.utils import jwt_payload_handler jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # rest_framework_jwt.utils.jwt_encode_handler jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER from .models import User # 自定义签发表签发 class UserView(APIView): def post(self, request): # 拿到前端提交的用户名、密码去表里查询 username = request.data.get('username') password = request.data.get('password') user = User.objects.filter(username=username, password=password).first() if user: # 查询到了,说明用户名、密码正确,进行token签发 # 通过user生成payload,jwt中有提供一个方法: payload = jwt_payload_handler(user) # jwt提供的方法:通过payload生成token token = jwt_encode_handler(payload) return Response({'code': 100, 'msg': '登录成功', 'token': token, 'username': user.username}) else: return Response({'code': 101, 'msg': '用户名或者密码错误'})
路由:
urlpatterns = [ path('admin/', admin.site.urls), path('login/',UserView.as_view()), # 自定义表签发路由 path('test/', TestView.as_view()), #自定义表认证的测试接口路由 ]
视图类:
# 测试接口 from rest_framwork.views import APIView from .auth import JwtAuthentication # 测试接口 class TestView(APIView): # 登录之后才能访问 authentication_classes = [JwtAuthentication] def get(self,request): print(request.user) # User object (1) return Response({'code':100,'msg':'测试成功'})
postman测试结果:
二、 django-jwt源码分析
签发源码分析:
1. 入口:obtain_jwt_token
-from rest_framework_jwt.views import obtain_jwt_token
2. obtain_jwt_token的本质:ObtainJSONWebToken.as_view()
3. 看ObtainJSONWebToken视图类
- 前端POST请求,提交了用户名和密码,就能签发token
- 去 ObtainJSONWebToken中找post方法
4. 去父类JSONWebTokenAPIView中找post方法,
5. 校验用户名密码和生成token,写在了序列化类:JSONWebTokenSerializer的全局钩子validate中:
总结:
- 前端携带用户名、密码到后端,执行后端的post方法,后端生成一个序列化类的对象
- serializer.is_valid(),进行数据校验,走了全局钩子validate
- 全局钩子中通过用户名和密码获取用户,如果获取不到,就抛异常
- 获取到之后签发token
- 签发完后返回,在视图类中,取出来,返回给前端
认证源码分析:
1. 从哪里看----》认证类:JSONWebTokenAuthentication
2. JSONWebTokenAuthentication:
从父类BaseJSONWebTokenAuthentication类中找到了authenticate方法:
三、权限介绍
所有项目都会有权限控制
1. ACL(访问控制列表)
ACL是访问控制列表(Access Control List),针对互联网用户,多半是这个
在ACL中,将用户与权限对接(多对多):一个用户可以有多个权限,一个权限可以被多个用户拥有
比如:张三:[发视频,点赞,评论]
李四:[看视频]
2. RBAC(基于角色的访问控制)
RBAC 是基于角色的访问控制(Role-Based Access Control ):公司内部项目
在 RBAC 中,将权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。django的 admin+auth 就是使用了这套认证机制。
python写公司内部项目比较多,使用rbac控制居多
如何设计:
-用户表---》一堆用户:张三,李四
-角色表(group组)---》用户的角色:后勤部,开发部,总裁办。。。
-权限表-----》放了一堆权限:发电脑,提交代码,删除代码,发工资
-用户和角色多对多:一个用户属于多个角色,一个角色属于多个用户
-角色 和权限多对多:一个角色有多个权限,一个权限属于多个角色
--------rabc----通过5张表可以实现
-django为了更细粒度划分---》多了一张表,用户和权限多对多
演示django的RABC权限控制:
3. ABAC(基于属性的访问控制)
ABAC是基于属性的访问控制(Atrribute-Based Access Control),又称为PBAC(Policy-Based Access Control,基于策略的访问控制),CBAC(Claims-Based Access Control,基于声明的访问控制)。
传统的ACL、RBAC的架构是{subject,action,object},而ABAC的架构是{subject,action,object,contextual}且为他们添加了parameter(参数)。
subject属性:比如用户的年龄、部门、角色、威望、积分等主题属性
action属性:比如查看、读取、编辑、删除等行为属性
object属性:比如银行账户、文章、评论等对象或资源属性
contextual属性:比如时段、IP位置、天气等环境属性
四、simpleui的使用
公司内部,做公司内的项目需要使用这套权限控制
方案一:使用django-admin写
有的公司,不怎么写前端,直接使用django的admin,快速写出一套具有权限管理的系统
django-admin的界面不好看:第三方美化---》simpleui
方案二:自己写,前端使用vue,后端使用django,做公司内部的项目
- 第三方开源的权限控制 项目
- python界:django-vue-admin
- java界:若依
- go界:gin-vue-admin
标签:自定义,jwt,token,源码,user,import,权限,payload From: https://www.cnblogs.com/Lucky-Hua/p/17697198.html