一、什么是Token?

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器会生成一个Token并将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

二、为什么要使用Token?

在很多项目案例中,需要实现账户的功能,客户端所有的功能都基于用户已登陆的前提下才可以使用。这就要求每次客户端像服务器请求数据时都要验证账户是否正确,如果正确则按正常方式返回数据,如果错误则进行拦截并返回错误信息。但是当客户端频繁向服务器请求数据的话,每次服务器都要频繁地查询数据库。而Token正是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。并取代传统使用session的方法来进行验证。

三、JWT json-web-token

  1.三大组成

    1,header

    格式为字典,元数据格式如下  

{'alg':'HS256', 'typ':'JWT'}
#alg代表要使用的 算法
#typ表明该token的类别 - 此处必须为 大写的 JWT

     该部分数据需要转成json串并用base64加密

    

    2,payload

    格式为字典,此部分分为公有声明和私有声明

    公共声明:JWT提供了内置关键字用于描述常见的问题

    此部分均为可选项,用户根据自己需求 按需添加key,常见公共声明如下:

{'exp':xxx, # Expiration Time 此token的过期时间的时间戳
'iss':xxx,# (Issuer) Claim 指明此token的签发者
'aud':xxx, #(Audience) Claim 指明此token的
'iat':xxx, # (Issued At) Claim 指明此创建时间的时间戳
'aud':xxx, # (Audience) Claim 指明此token签发面向群体
}

    私有声明:用户可根据自己业务需求,添加自定义的key,例如如下:

{'username': 'guoxiaonao'}

    公共声明和私有声明均在同一个字典中;转成json串并用base64加密

    3,sign 签名

    签名规则如下:

    根据header中的alg确定具体算法,以下用 HS256为例

    HS256(自定义的key , base64后的header + '.' + base64后的payload)

    解释:用自定义的key, 对base64后的header + '.' + base64后的payload进行hmac计算

  2,jwt结果格式

    base64(header) + '.' + base64(payload) + '.' + base64(sign)

    最终结果如下: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imd1b3hpYW9uYW8iLCJpc3MiOiJnZ2cifQ.Zzg1u55DCBqPRGf9z3-NAn4kbA-MJN83SxyLFfc5mmM'

  3,校验jwt规则

    1,解析header, 确认alg

    2,签名校验 - 根据传过来的header和payload按 alg指明的算法进行签名,将签名结果和传过来的sign进行对比,若对比一致,则校验通过

    3,获取payload自定义内容

  4,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/str 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

老师手写的Jwt类,很厉害:

import base64
import copy
import hmac
import json
import time class Jwt(): def __init__(self):
pass @staticmethod
def encode(payload, key, exp=300): #init header
header = {'typ': 'JWT', 'alg': 'HS256'}
#separators - 指定序列化后的json串格式, 第一个参数
#指每个键值对之间的连接符号,第二个参数指的是每一个键值对中键和值之间的连接符号
#sort_keys - 将序列化后的字符串进行排序
header_json = json.dumps(header, separators=(',',':'), sort_keys=True)
#生成b64 header
header_bs = Jwt.b64encode(header_json.encode()) #参数中的 payload {'username': 'aaa'}
payload = copy.deepcopy(payload)
#添加公有声明 - exp 且值为未来时间戳
payload['exp'] = int(time.time()) + exp
payload_json = json.dumps(payload, separators=(',',':'), sort_keys=True)
payload_bs = Jwt.b64encode(payload_json.encode()) #签名
#判断传入的key的类型
if isinstance(key, str):
key = key.encode()
hm = hmac.new(key, header_bs + b'.' + payload_bs, digestmod='SHA256')
hm_bs = Jwt.b64encode(hm.digest()) return header_bs + b'.' + payload_bs + b'.' + hm_bs @staticmethod
def b64encode(j_s):
#替换生成出来的b64串中的占位符 =
return base64.urlsafe_b64encode(j_s).replace(b'=',b'') @staticmethod
def b64decode(b64_s): rem = len(b64_s) % 4
if rem > 0:
b64_s += b'=' * (4-rem)
return base64.urlsafe_b64decode(b64_s) @staticmethod
def decode(token, key):
#校验两次HMAC结果
#检查exp公有声明的有效性
#注意 b64 = 要补全
#校验成功 返回 payload 字典对象, 失败的话 raise
header_b , payload_b , sign = token.split(b'.') if isinstance(key, str):
key = key.encode()
#比较两次HMAC结果
hm = hmac.new(key, header_b + b'.' + payload_b, digestmod='SHA256')
if sign != Jwt.b64encode(hm.digest()):
raise JwtSignError('---sign error !!! ')
#获取payload
payload_json = Jwt.b64decode(payload_b)
payload = json.loads(payload_json.decode())
#校验exp是否过期
exp = payload['exp']
now = time.time()
if now > exp:
#过期
raise JwtExpireError('---The token is expire !!!') return payload class JwtSignError(Exception): def __init__(self, error_msg):
self.error_msg = error_msg def __str__(self):
return '<JwtSignError is %s>'%(self.error_msg) class JwtExpireError(Exception): def __init__(self, error_msg):
self.error_msg = error_msg def __str__(self):
return '<JwtExpireError is %s>' % (self.error_msg) if __name__ == '__main__': s = Jwt.encode({'username':'guoxiaonao'}, 'abcde') #time.sleep(2) #res = Jwt.decode(s, 'abcde')
print(s)

Django 利用JWT实现前后端分离的Token验证的更多相关文章

  1. SpringBoot20 集成SpringSecurity02 -> 利用SpringSecurity进行前后端分离的登录验证

    1 SpirngBoot环境搭建 创建一个SpringBoot项目即可,详情参见三少的相关博文 参考博文 -> 点击前往 SpirngBoot项目脚手架 -> 点击前往 2 引入Spirn ...

  2. SpringBoot使用SpringSecurity搭建基于非对称加密的JWT及前后端分离的搭建

    SpringBoot使用SpringSecurity搭建基于非对称加密的JWT及前后端分离的搭建 - lhc0512的博客 - CSDN博客 https://blog.csdn.net/lhc0512 ...

  3. 从零玩转SpringSecurity+JWT整合前后端分离

    从零玩转SpringSecurity+JWT整合前后端分离 2021年4月9日 · 预计阅读时间: 50 分钟 一.什么是Jwt? Json web token (JWT), 是为了在网络应用环境间传 ...

  4. 前后端分离使用 Token 登录解决方案

    前后端分离使用 Token 登录解决方案:https://juejin.im/post/5b7ea1366fb9a01a0b319612

  5. Spring Security + JWT实现前后端分离权限认证

    现在国内前后端很多公司都在使用前后端分离的开发方式,虽然也有很多人并不赞同前后端分离,比如以下这篇博客就很有意思: https://www.aliyun.com/jiaocheng/650661.ht ...

  6. 利用gulp解决前后端分离的header/footer引入问题

    在我们进行前后端完全分离的时候,有一个问题一直是挺头疼的,那就是公共header和footer的引入.在传统利用后端渲染的情况下,我们可以把header.footer写成两个单独的模板,然后用后端语言 ...

  7. JWT 在前后端分离中的应用与实践

    关于前后端分离 前后端分离是一个很有趣的议题,它不仅仅是指前后端工程师之间的相互独立的合作分工方式,更是前后端之间开发模式与交互模式的模块化.解耦化.计算机世界的经验告诉我们,对于复杂的事物,模块化总 ...

  8. Shrio使用Jwt达到前后端分离

    概述 前后端分离之后,因为HTTP本身是无状态的,Session就没法用了.项目采用jwt的方案后,请求的主要流程如下:用户登录成功之后,服务端会创建一个jwt的token(jwt的这个token中记 ...

  9. 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目

    一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...

随机推荐

  1. 5、numpy——切片和索引

    1.一维数组 1.1 一维数组很简单,基本和列表一致.ndarray 数组可以基于 0 - n 的下标进行索引. 切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step ...

  2. CodeChef Sereja and GCD

    Sereja and GCD   Problem code: SEAGCD   Submit All Submissions   All submissions for this problem ar ...

  3. DTS

    一.DTS的加载过程   如果要使用Device Tree,首先用户要了解自己的硬件配置和系统运行参数,并把这些信息组织成Device Tree source file.通过DTC(Device Tr ...

  4. KMP,Trie,AC自动机题目集

    字符串算法并不多,KMP,trie,AC自动机就是其中几个最经典的.字符串的题目灵活多变也有许多套路,需要多做题才能体会.这里收集了许多前辈的题目做个集合,方便自己回忆. KMP题目:https:// ...

  5. rabbiitmq非阻塞调用

    https://blog.csdn.net/panxianzhan/article/details/50755409 https://blog.csdn.net/u013946356/article/ ...

  6. Object.assign()遇到的问题分析

    概念 Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象.语法如下: Object.assign(target, ...sources) Obj ...

  7. websock(AMQ)通信-前端

    服务端和客户端之间的通信 前端开发经常会依赖后端,那么如果后端服务器还没做好推送服务器,那么前端该如何呢.最简单的就是自己模拟一个服务器,用node来搭建,这边只简单介绍搭建的过程 node搭建服务器 ...

  8. 前端每日实战:50# 视频演示如何用纯 CSS 创作一个永动的牛顿摆

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKmGaJ 可交互视频教程 此视频 ...

  9. IBM和DoE推出世界上最快的超级计算机

    IBM和美国能源部的橡树岭国家实验室今天发布了该部门最新的超级计算机Summit.IBM声称峰会目前是世界上“最强大,最聪明的科学超级计算机”,其峰值性能每秒高达20万亿次.当新的榜单在本月晚些时候发 ...

  10. BZOJ3625 CF438E 小朋友与二叉树

    心态崩了 不放传送门了 辣鸡bz 还是正经一点写一下题解= = 就是显然我们可以把权值写成生成函数形式g(0/1序列)来表示权值是否出现 然后f来表示总的方案数 可以列出 分别枚举左右子树和空树的情况 ...