从drf切换到django-ninja。
drf是一个传统以model驱动的rest框架,可以对一个模型进行CURD。但fastapi给了我一个提示,现代后端系统不完全是一个rest标准,不是把model当成资源这么简单,会涉及到缓存、nosql,分布式等等。传统rest api应用起来挺麻烦。
django-ninja与fastapi“长得”几乎一样,就是受fastapi启发,但可以与django原生生成整合到一起,即可以获得django的orm, admin的优势,同时还可以获得fastapi的异步,swagger,pydantic的数据校验能力。
api本身就是一个json_response,对一个dict字典结构进行序列化后返回的过程。ninja类似fastapi做了入参与出参自动解析与校验的工作,可以省下我们一些工作量,另外就是swagger的界面整合,还是router路由等。
当然api工作本身有一个权限与认证的过程,这个相对更加重要。现在前后端分离不可能使用session-auth,这个基本不用了,主要是jwt的token认证机制。
今天我们主要搞搞基本django-ninja的jwt机制。
from ninja.security import HttpBearer
class AuthBearer(HttpBearer):
def authenticate(self, request, token):
if token == "supersecret":
return token
header里需要带 Authorization字段, Bearer TOKEN。
curl -X 'GET' \
'http://127.0.0.1:8000/api/common/test_auth' \
-H 'accept: */*' \
-H 'Authorization: Bearer aaa'
这个HttpBearer是会从header里取出Authorization后面的TOKEN。
这里的auth可以是任意可执行的函数,比如校验ip的黑白名单等。还有api key的场景,无论是在query key,header里或者cookie里,ninja都有一些支持,其实自己实现也不复杂。
https://github.com/jmwri/simplejwt
simplejwt封装了encode, decode功能。
from datetime import datetime
from simplejwt.jwt import Jwt, decode
SECRET_KEY = '123456'
# token 有效时间 时 分 秒
TOKEN_LIFETIME = 12 * 60 * 60
class JwtUtils:
@staticmethod
def get_token(payload):
time_now = int(datetime.now().timestamp())
valid_to = time_now + TOKEN_LIFETIME
jwt = Jwt(secret=SECRET_KEY, payload=payload, valid_to=valid_to)
return jwt.encode()
@staticmethod
def get_payload(token):
return decode(SECRET_KEY, token)[1]
@staticmethod
def is_timeout(payload):
time_now = int(datetime.now().timestamp())
if payload['exp'] < time_now:
return True
else:
return False
if __name__ == '__main__':
token = JwtUtils.get_token({'username': 'admin'})
print(token)
payload = JwtUtils.get_payload(token)
print(payload)
print(JwtUtils.is_timeout(payload))
本质上,就是把一个字典进行加密,使用同一个SECRET_KEY可以对数据进行解密,取出数据。
使用如下AuthBearer可以给任意一个api请求做jwt校验,token是自动获取的,其实就是从header里的meta取出authorization里的token。然后写自己的检验逻辑即可。若返回False就是一个401的错误。
class AuthBearer(HttpBearer):
def authenticate(self, request, token):
payload = JwtUtils.get_payload(token)
username = payload.get('username')
print(username)
# if username == 'admin':
# return False
return True
校验成功之后,类似session机制,需要拿到current_user对象,session验证是把对象保存在session里,而jwt模式下,可以从token里解出user_info。
@router.get("/test_auth", auth=AuthBearer())
def bearer(request):
user_info = get_user_info_from_token(request)
return {'message': 'test_auth正常使用', 'user_info': user_info}
get_user_info_form_token的代码如下:
def get_user_info_from_token(request):
token = request.META.get("HTTP_AUTHORIZATION")
token = token.split(" ")[1]
user_info = JwtUtils.get_payload(token)
return user_info
其实框架只是把一些例行性的功能做了封装。
在熟悉机制之后用比较好,省不少模板代码。但从学习的角度,还是自己从更基础的代码开始实现会更好掌握。
小结:
前后端分享django+ ninja是个不错的选择。
标签:info,authenticate,return,get,token,user,文章,ninja,payload From: https://www.cnblogs.com/lxgbky/p/17520801.html