Django前后端分离1——jwt
一.前戏
1.base64
方法 | 作用 | 参数 | 返回值 |
---|---|---|---|
b64encode | 将输入的参数转化为base64规则的串 | 预加密的明文,类型为bytes;例:b‘guoxiaonao’ | base64对应编码的密文,类型为bytes;例:b’Z3VveGlhb25hbw==’ |
b64decode | 将base64串 解密回 明文 | base64密文,类型为bytes;例:b’Z3VveGlhb25hbw==’ | 参数对应的明文,类型为bytes;例:b’guoxiaonao’ |
urlsafe_b64encode | 作用同b64encode,但是会将 ‘+‘替换成 ‘-’,将’/‘替换成’_’ | 同b64encode | 同b64encode |
urlsafe_b64decode | 作用同b64decode | 同b64decode | 同b64decode |
import base64s = b'guoxiaonao'
b_s = base64.b64encode(s) # b_s打印结果为 b'Z3VveGlhb25hbw=='#base64解密
ss = base64.b64decode(b_s) # ss打印结果为 b'guoxiaonao'
2.SHA-256 安全散列算法的一种(hash)
import hashlib
s = hashlib.sha256() # 创建sha256对象
s.update(b'xxxx') # 添加欲hash的内容,类型为 bytes
s.digest() # 获取加密后的摘要
3.HMAC-SHA256 是一种通过特别计算方式产生的消息认证码,使用散列算法同时结合一个加密密钥。它可以用来保证数据的完整性,同时可以用来作某个消息的身份验证
import hmac
# 生成hmac对象
# 第一个参数为加密密钥key,bytes类型,
# 第二个参数为欲加密的串,bytes类型
# 第三个参数为hmac的算法,指定为SHA256
h = hmac.new(key, str, digestmod='SHA256 ')
h.digest() #获取最终结果
4.RSA256 非对称加密
- 加密: 公钥加密,私钥解密
- 签名: 私钥签名, 公钥验签
二.JWT:json web token
1.组成
- header:格式为字典,该部分数据需要转成json串并用base64 加密
{'alg':'HS256', 'typ':'JWT'}
# alg代表要使用的 算法
# typ表明该token的类别 - 此处必须为 大写的 JWT
- payload:格式为字典-内部存有 公有声明 和 私有声明
公共声明:可选项,根据自己需求 按需添加,JWT提供了内置关键字用于描述常见的问题
私有声明:根据自己业务需求
公共声明和私有声明均在同一个字典中;转成json串并用base64加密
{# 常见的公有声明
'exp':xxx, # Expiration Time 此token的过期时间的时间戳
'iss':xxx,# (Issuer) Claim 指明此token的签发者
'aud':xxx, # (Audience) Claim 指明此token签发面向群体,安卓,ios,浏览器等
'iat':xxx, # (Issued At) Claim 指明此创建时间的时间戳# 私有申明按业务需求添加,如:
'username': 'kzzf',
}
- signature 签名
签名规则:根据header中的alg确定 具体算法,以下用 HS256为例
用自定义的密钥key, 对base64后的header + ‘.’ + base64后的payload进行hmac计算
HS256(key , base64后的header + ‘.’ + base64后的payload)
2.jwt的最终面貌
base64(header) + ‘.’ + base64(payload) + ‘.’ + base64(sign)
b’eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imd1b3hpYW9uYW8iLCJpc3MiOiJnZ2cifQ.Zzg1u55DCBqPRGf9z3-NAn4kbA-MJN83SxyLFfc5mmM’
3.jwt校验规则
- 解析header, 确认alg
- 签名校验:
根据传过来的header和payload按 alg指明的算法进行签名(签名时需要用到服务端自定义的密钥),将签名结果和传过来的sign进行对比,若对比一致,则校验通过 - 获取payload自定义内容
三.手写JWT的生成和验证
import base64, hmac, json, time
import copy# 自定义类,提供jwt的加密和接密接口
class Jwt:def __init__(self):pass@staticmethoddef encode(payload, key, exp=300):# 创建headerheader = {"alg": "HS256", "typ": "JWT"}# separators参数:生成紧凑型的json字符串(原字典中如果有空格的话,转成json后默认是会保留的)# 指明json字符串中 每个键值对 以及 key和value之间 用什么相连# sort_key:json字符串按key排序输出,保证每次转换之后得到相同的字符串(因为字典是无序的)header_j = json.dumps(header, separators=(',', ':'), sort_keys=True)# 使用自定义的b64encode方法进行加密header_bs = Jwt.b64encode(header_j.encode())# 创建payloadpayload = copy.deepcopy(payload)# 设置过期时间标记payload['exp'] = int(time.time()) + exppayload_j = json.dumps(payload, separators=(',', ':'), sort_keys=True)# 使用python提供的base64方法加密payload_bs = base64.urlsafe_b64encode(payload_j.encode())# 生成sign 预签名串to_sign_str = header_bs + b'.' + payload_bsif isinstance(key, str):key = key.encode()# 创建加密对象,hamc new 中的参数需要用bytes格式hmac_obj = hmac.new(key, to_sign_str, digestmod='SHA256')# 获得签名的摘要(结果)sign = hmac_obj.digest()sign_bs = Jwt.b64encode(sign)return header_bs + b'.' + payload_bs + b'.' + sign_bs# jwt解密方法,返回payload@staticmethoddef decode(token, key):'''校验token:param token::param key::return:'''header_bs, payload_bs, sign = token.split(b'.')if isinstance(key, str):key = key.encode()# 重新计算签名hmac_obj = hmac.new(key, header_bs+b'.'+payload_bs, digestmod='SHA256')new_sign = Jwt.b64encode(hmac_obj.digest())if sign != new_sign:# 当前传过来的token违法,raise异常,由外部进行捕获raise JwtError('token不合法')# token验证合法,判断是否过期# 将base64的payload解码为json串,这里得到的是bytes格式payload_j = Jwt.b64decode(payload_bs)print(type(payload_j))payload = json.loads(payload_j)# 拿到过期时间exp = payload['exp']now = time.time()# 对比是否过期if now > exp:raise JwtError('token已过期')return payload@staticmethoddef b64encode(s):# 原生base64编码:每3个字符进行编码,最终可能出现等号,此处将等号替换掉,解码时也要做对应的处理return base64.urlsafe_b64encode(s).replace(b'=', b'')@staticmethoddef b64decode(bs):# 将编码时=替换为''的进行恢复,补足长度rem = len(bs) % 4bs += b'=' * (4-rem)return base64.urlsafe_b64decode(bs)# 自定义jwt异常类
class JwtError(Exception):def __init__(self, error_msg):self.error = error_msgdef __str__(self):return '<JwtError error %s>' % self.errorif __name__ == '__main__':res = Jwt.encode({'username':'kzzf'}, 'abcd1234')print(Jwt.decode(res, 'abcd1234'))
四.pyjwt
pip3 install pyjwt
方法 | 参数说明 | 返回值 |
---|---|---|
encode(payload, key, algorithm) |
payload: jwt三大组成中的payload,需要组成字典,按需添加公有声明和私有声明 例如: {‘username’: ‘guoxiaonao’, ‘exp’: 1562475112} 参数类型: dict |
token串 返回类型:bytes |
key : 自定义的加密key 参数类型:str |
||
algorithm: 需要使用的加密算法[HS256, RSA256等] 参数类型:str |
||
decode(token,key,algorithm,) |
token: token串 参数类型: bytes |
payload明文 返回类型:dict |
key : 自定义的加密key ,需要跟encode中的key保持一致 参数类型:str |
||
algorithm: 同encode | ||
issuer: 发布者,若encode payload中添加 ‘iss’ 字段,则可针对该字段校验 参数类型:str |
若iss校验失败,则抛出jwt.InvalidIssuerError | |
audience:签发的受众群体,若encode payload中添加’aud’字段,则可针对该字段校验 参数类型:str |
若aud校验失败,则抛出jwt.InvalidAudienceError |
PS: 若encode的时候 payload中添加了exp字段,则exp字段的值需为 当前时间戳+此token得有效期时间, 例如希望token 300秒后过期 {‘exp’: time.time() + 300}; 在执行decode时,若检查到exp字段,且token过期,则抛出jwt.ExpiredSignatureError
五.客户端tokne的生命周期
1.用户未登录:前端 肯定是没有token的
2.用户执行注册/登录
- 一旦基础数据校验成功,后端生成token, 并且token包含此次注册/登录用户的用户名;并通过response返回给前端[json]
- 前端拿到response 的token后,将token存入到浏览器本地存储 ;方法如右:window.localStorage.setItem(‘dnblog’, token)
3.用户每次访问应用
- 从本地存储中拿出token ,window.localStorage.getItem(‘dnblog’)
- JS 将 token 放入 request 的 Authorization 头,发送http 请求向后端索要数据
- 服务器-接到前端请求【当前URL 加了 loging_check,并且请求方法在 methods参数中】:ex: loging_check(‘POST’), 则当前URL POST方法时进行如下校验
1,从 request Authorization 头 拿出token,
2,校验
3,校验不通过,返回前端异常码
4,校验通过,正常执行对应URL的视图函数 - 前端一旦接到 关于token的 异常码, 则删除本地存储中的token;
且将用户转至登录界面
token解决了前后端分离时的登陆状态问题,但不能解决安全问题,安全问题需要从协议层如https来解决
Django前后端分离1——jwt相关推荐
- Django前后端分离实现登录验证码功能
Django前后端分离实现登录验证码功能 当下最流行最热门的开发方式当属前后端分离开发,分工也更加明确与专注,前端也是越来越难,几天不学习就跟不上节奏,一个月不学习可以好不夸张的说,你已经不适合这个行 ...
- 前后端分离之JWT用户认证
前后端分离之JWT用户认证 在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时 ...
- 视频教程-Python+Vue+Django前后端分离项目实战-Python
Python+Vue+Django前后端分离项目实战 教学风格独特,以学员视角出发设计课程,难易适度,重点突出,架构清晰,将实战经验融合到教学中.讲授技术同时传递方法.得到广大学员的高度认可. 王进 ...
- 视频教程-Angular+Django前后端分离实战项目开发教程-AngularJS
Angular+Django前后端分离实战项目开发教程 胜蓝博创(韬略课堂)创始人,IT培训讲师,先后在蓝港在线,热酷,乐元素等大型游戏公司任职,参与过多款大型网游.手游的设计和开发,精通页游.手游前 ...
- Django CSRF(什么是CSRF?)\Django前后端分离csrf token获取方式
文章目录 Django CSRF 什么是CSRF? Django CSRF Django CSRF 中间件 Django,Ajax提交csrf_token处理 Django 设置 cookie 中的 ...
- Nginx+uwsgi+celery+supervisor部署Django前后端分离项目
转载 Nginx+uwsgi+celery+supervisor部署Django前后端分离项目 ljmict 0人评论 3887人阅读 2018-08-08 01:29:45 本实验实现了负载均衡.反 ...
- Django 前后端分离实战项目 生鲜超市(七)之Vue展示商品分类数据和搜索
Vue展示商品分类数据和搜索 前言 所有vue接口全部在src/api/api.js文件下 代码已上传至github:https://github.com/kalipoison/fresh-marke ...
- [转] 前后端分离之JWT用户认证
[From] http://www.jianshu.com/p/180a870a308a 在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当 ...
- SpringSecurity-02-基于前后端分离和JWT载体的认证授权
文章目录 1:基本概念 1:什么是认证 2:什么是会话 3.什么是授权 2:准备工作 1:分析基于jwt的登录过程 2:springsecurity原理 3:security登录认证使用 1:认证流程 ...
最新文章
- Java 线程 知识
- java paint 怎么用_java如何使用paint方法画图
- Hadoop 倒排索引
- 【剑指offer】面试题26: 树的子结构(Java)
- 基于CAShapeLayer和贝塞尔曲线的圆形进度条动画
- 手机正在录音怎么隐藏
- 使用FFMPEG类库分离出多媒体文件中的音频码流
- ASP.net 的URL路由选择(System.Web.Routing.dll)
- EGO走进美团——追寻千亿市场背后的技术力量
- 深度linux wubildr.mbr,把玩Linux何须安装
- 在商业化道路上,小冰还要再多走几步
- 台式计算机上的fn键是哪个,电脑键盘上Fn键到底有什么用?
- 程炳皓很明智陈一舟不吃亏
- 【Pycharm教程】Pycharm下载安装、配置与测试
- 日本战国武将绰号与称号一览表
- D3 天眼查 股权结构图
- 市场已经统一-网博汇智
- eclipse 打不开,弹出一个框。
- CSI笔记【2】:正交频分多路复用技术/OFDM
- 交叉编译ffmpeg+移植Hi3536板子
热门文章
- COleDateTime 时间操作
- java ftp服务器搭建教程_配置使用IIS的FTP服务器客户端实现 (Java)教程
- 全志r16android sdk,全志R16_sdk_Dmaengine使用手册
- 微型计算机输入输出设备ppt,微型计算机地输入输出设备.ppt
- 赢在未来 | 升级营销模式,蚓链让企业业绩增长N倍
- 第十三届蓝桥杯大赛软件类决赛Java大学B组C题——左移右移
- kubernetes源码分析-pod创建流程
- 使用aiohttp 抓取起点小说网
- 十进制转十六进制(python)
- 无刷直流电机介绍及单片机控制实例