1.JWT的介绍:
- JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。
- 官方文档
2.JWT && JWS && JWE
- JWT包括JWS和JWE,如下图
- JWS简单介绍:
- JSON Web Signature是一个有着简单的统一表达形式的字符串:
- JWS包括Heard,Payload,Signature三部分
- JWE简单介绍:
- 相对于JWS,JWE则同时保证了安全性与数据完整性。JWE由五部分组成:
- Heard、JWE Encrypted Key、Initialization Vector、Ciphertext、Authentication Tag
- 具体生成步骤为:
1.JOSE含义与JWS头部相同。
2.生成一个随机的Content Encryption Key (CEK)。
3.使用RSAES-OAEP 加密算法,用公钥加密CEK,生成JWE Encrypted Key。
4.生成JWE初始化向量。
5.使用AES GCM加密算法对明文部分进行加密生成密文Ciphertext,算法会随之生成一个128位的认证标记Authentication Tag。
6.对五个部分分别进行base64编码。
可见,JWE的计算过程相对繁琐,不够轻量级,因此适合与数据传输而非token认证,但该协议也足够安全可靠,用简短字符串描述了传输内容,兼顾数据的安全性与完整性。
3.Python的JWT
- itsdangerous
- JSONWebSignatureSerializer
- TimedJSONWebSignatureSerializer (可设置有效期)
- pyjwt
- pyjwt使用
- 1.安装
- 2.例子(官方)
>>> import jwt
>>> encoded_jwt = jwt.encode({
'some': 'payload'}, 'secret', algorithm='HS256')
>>> encoded_jwt
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg'
>>> jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])
{
'some': 'payload'}
- 3.命令行
pyjwt --key=secret decode TOKEN
pyjwt decode --no-verify TOKEN
4.举个栗子(运用在网站上)
- ①.需求:实现简单的网站业务逻辑,有首页,个人中心,登录。进行分析
- ②.初级分析:
- 1.不需要登录的页面,如:首页。
- 2.需要登陆的网页,如:个人中心。
- 3.登录页面登陆时,服务端返回给客户端携带用户信息以及有效期的token。
- 4.当用户想访问个人中心时,客户端将token发送给服务端,若token为空以及没有token字段,都跳转到登录界面。
- 5.如果token存在,需要检测token的有效期,如果token失效以及token错误,都跳转用户登录页面,重新登陆,重新获取新的token。
- ③.中级分析
- 1.当客户端传递给服务端token时,如果token错误,应该和空token归为一类,都需要返回到登录页面,登录以获取token。
- 2.若token过期(token需要频繁更换,否则有可能会被窃取破解),此时如果让用户去登陆,会显得非常麻烦,毕竟在逐渐智能化的时代,方便快捷的网页应用才会深得人心。借鉴wechat类APP应用几乎是登录一次,一年半载都不需要用户手动输入密码频繁登录。
- 3.此时,可以想到的是在用户进行首次登陆时,返回给客户端两个token。一个token用于平常验证,过期时间短。另一个未过期(此token过期时间较长)refresh_token用于当token过期时,换取新的token值,以及一个新的refresh_token。
- 为什么要返回一个新的refresh_token呢?
- 答:保证token和refresh_token的状态时同生型,即重新刷新refresh_token的过期时间,能够循环往返,达到登陆状态持久化。
- 四.深入分析(注:此时只把refresh_token的业务逻辑完善。)
- 0.(承接初级分析1,2,3,4,其中3处服务端需要返回客户端token,refresh_token。4处需要加入token错误判断)
- 1.如果token存在且正确,直接进入个人中心页面。
- 2.如果token存在却过期,就需要给客户端发送相应以及携带专属响应状态码。
- 3.客户端接收到响应状态后,紧接着将refresh_token发送给服务端。服务端接收到refresh_token,判断是否存在,若不存在,跳转登陆页面。
- 4.若存在,判断refresh_token是否过期(将要过期【可有可无】)以及是否正确。
- 5.若过期或者不正确(因为jwt.decode(refresh_token)会判断过期时间以及正确与否的判断),则跳转到登录界面,进行登录。
- 5.若refresh_token未过期并且正确,则换取新的token值以及新的refresh_token值。
5.上代码!!!
import datetime
import json
from time import mktime
from rediscluster import RedisCluster
from flask_sqlalchemy import SQLAlchemy
import jwt
from flask import Flask, request, g, jsonify, redirect, url_for
from flask_restful import Api, Resource
import random
"""
1.此处采用了redis集群以及flask,mysql
"""
class Config(object):
key = 'woobrain'
algorithm = 'HS256'
exp_time = {
'days': 12,
'hours': 2,
'minutes'