赞
踩
1.前置准备
pip install pyjwt(默认安装最新版)
2.jwt三个部分的介绍
2.1Header
头部包含两部分,一个是token的类型,另一个是加密类型
2.2payload
payload是装载在jwt中的一些有效信息,是可以自定义的一部分,比如我想在验证完这个jwt之后直接取到用户的id,昵称之类的,就可以放在这个地方,怎么取到后面会说
这里放的是wx小程序里main获取的openid和过期时间
2.3signature
这个部分是整个jwt最核心的地方,他需要经过base64url编码的header,payload,以及我们提供的一把密钥,通过header中指定的算法(这里是HS256)算出的一个字符串
得到header,payload和signature后用‘.’连接就得到了jwt
eg:
eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJvcGVuaWQiOiIoJ29RdVdsNVdGeWdscEpVb2tJQ2N5U25PZWJ3TWsnLCkiLCJleHAiOjE3MDkyMTM4NDZ9.2BT5AhrkYB5ww0jetD7qIz9DntXmXbYYdOTHdxMO9Wo
2.4解密原理
1.后端接收到前端传来的token
2.对token进行分割(分成header,payload,signature)
3.对payload进行base64url解密得到payload中的信息
4.将header和payload拼接后进行HS256加密看是否等于base64解密的signature,如果相等则验证成功
3.1代码示例
在根目录下创建文件夹jwt.auth,创建py文件jwt.auth
文件代码如下:
一个用来创建jwt,一个用来验证jwt
- import jwt
- import datetime
- import djangoProject.settings
-
- def create_jwtToken(openid):
- expire_time = datetime.datetime.utcnow() + datetime.timedelta(days=7)
- headers = {
- 'typ': 'jwt',
- 'alg': 'HS256'
- }
-
- payload = {
- 'openid': openid,
- "exp": expire_time
- }
- result = jwt.encode(payload=payload, key=djangoProject.settings.SECRET_KEY, algorithm='HS256', headers=headers)
- return result
-
-
- def identify_token(token):
- try:
- verified_payload = jwt.decode(token, key=djangoProject.settings.SECRET_KEY, algorithms="HS256")
- #验证通过返回payload中的信息
- return verified_payload
- #不通过返回报错
- except jwt.ExpiredSignatureError:
- print('token已失效')
- return False
- except jwt.DecodeError:
- print('token认证失败')
- return False
- except jwt.InvalidTokenError:
- print('非法的token')
- return False
如果是2.x的python,create_jwtToken里面的result要写成
result = jwt.encode(payload=payload, key=djangoProject.settings.SECRET_KEY, algorithm='HS256', headers=headers).decode("utf-8")
3.x版本都是unicode就不用decode了
调用示例:
打印的结果(openid是隐私信息就用乱码代替了):
- eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJvcGVuaWQiOiIoJ29RdVdsNVdGeWdscEpVb2tJQ2N5U25PZWJ3TWsnLCkiLCJleHAiOjE3MDkyNzI2NDJ9.EZRwUn6fF7F5_qwFHxITu04blp6z6jP7L-BbAViCnhY
- {'openid': "('dafadfasfsdfafda',)", 'exp': 1709272642}
好了,现在我们已经有了生成jwt和验证jwt的方法,那具体在函数里面该怎么认证呢?
3.2jwt认证方式以及通过中间件添加全局认证
3.2.1单个函数添加认证
- def func(request):
- #我的前端是以在header中添加参数jwttoken来传递的,所以获取方式如下
- jwtToken = request.META['HTTP_JWTTOKEN']
- #如果是用url参数的方式传递也可以,用相应的方法获取token就行了
- res=jwt_auth.identify_token(jwtToken)
- if not res:
- return HttpResponse("TOKEN ERROR")
- #后面写正常流程即可
- #...
正常的话不会有任何反应,如果有问题的话会报错,然后阻断后面的函数执行(报错的方法写在认证那里了)
3.2.2通过中间件添加全局认证
如果只有几个函数还可以挨个添加,但如果有几百个函数呢,我们不可能去每个函数里面都加这几句,这个时候就需要中间件来帮忙了
在根目录下创建软件包middleware,包中创建py文件check_function_middleware
文件代码如下:
- from django.http import HttpResponse
- from django.urls import resolve
- from django.utils.deprecation import MiddlewareMixin
- from jwt_auth import jwt_auth
-
-
- class CheckFunctionMiddleware(MiddlewareMixin):
- #如果所有的视图函数都要检验token,那login界面也会无法触发,所以有部分函数是可以不需要验证token的
- #把这些函数的名字写在排除表中即可
- #如果函数是 def func(request):,在表中写func即可
- EXCLUDED_FUNCTIONS = ['login', 'getJwtToken', 'getToken']
- #这个函数在所有视图函数之前被触发,用来检验token的合法性刚好
- def process_request(self, request):
- jwtToken = request.META['HTTP_JWTTOKEN']
- #获取函数的名称
- path = request.path
- match = resolve(path)
- request_name = match.func.__name__
- #如果不在排除表中则触发
- if request_name not in self.EXCLUDED_FUNCTIONS:
- print("this func is not in the middleware dict")
- res=jwt_auth.identify_token(jwtToken)
- #检验不通过则返回错误
- if not res:
- return HttpResponse("TOKEN ERROR")
接下来只要全局注册一下中间件就行了
在setting.py中(路径写成CheckFunctionMiddleware类的路径就行):
至此,基本功能已经完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。