JWT 介绍 与 Itsdangerous 简易使用 (python)

JWT ( json web token ) 官网:

是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对对JWT进行签名

一、介绍:

JWT 和 Itsdangerous:地址 都是加密的 方法,

  • 但JWT 体积小,因而传输速度快

  • 传输方式多样,可以通过URL/POST参数/HTTP头部等方式传输严格的结构化。

它自身(在 payload 中)就包含了所有与用户相关的验证消息,如用户可访问路由、访问有效期等信息,服务器无需再去连接数据库验证信息的有效性,并且 payload 支持为你的应用而定制化。
支持跨域验证,可以应用于单点登录。

  1. 可以保证安全传输的前提下传送一些基本的信息,以减轻对外部存储的依赖,减少了分布式组件的依赖,减少了硬件的资源。
  2. 可实现无状态、分布式的Web应用授权,jwt的安全特性保证了token的不可伪造和不可篡改。
  3. 本质上是一个独立的身份验证令牌,可以包含用户标识、用户角色和权限等信息,以及您可以存储任何其他信息(自包含)。
  4. 任何人都可以轻松读取和解析,并使用密钥来验证真实性。

二、JWT的数据结构:

JWT 是由 Header(头部) Payload(载荷)Signature(签证)三部分组成。

xxx.yyy.zzz

 

Header(头部): 是一个描述JWT元数据的JSON对象

是由两部分组成 所属的类型 和 使用的算法 就比如 sha256(这是自己生命的算法 留给 签名加密使用)
然后 这个json 就被 base64 进行加密 成为 JWT 的 一部分

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。
{
"alg": "HS256",
"typ": "JWT"
}
alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);
typ属性表示令牌的类型,JWT令牌统一写为JWT。
最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

Payload(载荷): 七个默认字段 + 自定义私有字段

一般指的就是声明,用户 相关实体的声明(分为 公有 私有),还有索赔 不怎么重要 然后
继续 base64 编码 JWT 的第二部分

有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。
'''
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
'''

除以上默认字段外,我们还可以自定义私有字段,如下例:
{
"sub": "1234567890",
"name": "yuki",
"admin": true
}

注意
默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
JSON对象也使用Base64 URL算法转换为字符串保存。

 

签证 = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)

获取编码的标头,编码的有效载荷,机密,标头中指定的算法,并对其进行签名。
生成密钥 发送给服务器 这个密钥 只有 服务器和你知道。
然后加密 如 sha256(头部表明的) 签证就获得到了

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret),该密码仅仅为保存在服务器中,并且不能向用户公开。
然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。

三、项目中的应用:

四、Itsdangerous 应用:

import itsdangerous
import time
from itsdangerous import BadData

secret_key   = 'yuki' # 密钥

t = itsdangerous.TimedJSONWebSignatureSerializer(secret_key=secret_key , expires_in=6) # 过期事件6秒

info = {"username":"yuki", "user_id":1}

# ============加密 token =============
res = t.dumps(info)
token = res.decode() # 指定编码格式
print(token)
#eyJhbGciOiJIUzUxMiIsImlhdCI6MTU5NjE3NTQ2NSwiZXhwIjoxNTk2MTc1NTI1fQ.eyJ1c2VybmFtZSI6Inl1a2kiLCJ1c2VyX2lkIjoxfQ.RR0FjrMa1J7qCyoALDYPX0W3jt0QH2MCvX43w7SQITQMI4IVT7RItIQGOTPHwmnjidPob_Wp2zVR3Sk6FZMFuA
# ============解密 token =============


res = t.loads(token)
print(res)
try:
    time.sleep(7)
    # 当超时或值有误则会报错
    # res = t.loads('eyJhbGciOiJIUzUxMiIsImlhdCI6MTU5NjE3NTQ2NSwiZXhwIjoxNTk2MTc1NTI1fQ.eyJ1c2VybmFtZSI6Inl1a2kiLCJ1c2VyX2lkIjoxfQ.RR0FjrMa1J7qCyoALDYPX0W3jt0QH2MCvX43w7SQITQMI4IVT7RItIQGOTPHwmnjidPob_Wp2zVR3Sk6FZMFuA')
    res = t.loads(token)
    print(res)
except BadData as e:
    print('日期已过')


from itsdangerous.url_safe import URLSafeSerializer
# 签名加盐
# 若要签名的内容相同,就需要进行加盐,即起一个别名,空间命名spacename类似
s1 = URLSafeSerializer(secret_key="secret-key", salt="activate")
print(s1.dumps(42))

s2 = URLSafeSerializer(secret_key="secret-key", salt="upgrade")
print(s1.dumps(42))


s2.loads(s2.dumps(42))
# 不一致错误
try:
    s2.loads(s1.dumps(42))
except BadData as e:
    print(e)



猜你喜欢

转载自blog.csdn.net/qq_19707521/article/details/107716104
今日推荐