# 视频截图

视频来源

1663214458081

1663214824901

1663214871836

1663214915546

1663214947389

1663214990100

1663215058352

1663215147113

1663215206369

1663215264245

1663215298123

1663215406418

类似于中间件的功能,在执行视图函数之前先执行这个认证的功能。

1663215490790

1663215580959

验证类中有三种返回值

1663215660021

上面的 None 就是什么都不干

1663215710708

1663215730765

1663215796260

1663215855439

1663215895973

1663215930457

登录页面不用认证
1663216039753

1663216066508

jwt 官网

问题:
在生成 token 的时候需要用到用户名和密码这些前端返回的表单数据么?

# 代码如下

当前的官网

from django.test import TestCase
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drfdemo.settings')
django.setup()
from lyb.views import LybViewSet
from rest_framework import routers
from drfdemo import urls
from lyb.models import Lyb, MyUsers
import jwt
import datetime
if __name__ == '__main__':
    key = 'secretdfjsdf' # 自定义的值
    algorithm = "HS256"
    payload = {
        'id': 2,
        "name": "jack"
    }
    token = jwt.encode(payload=payload, key=key, algorithm=algorithm)
    print(token)
    res = jwt.decode(token, key=key, algorithms=algorithm)
    print(res)
'''
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwibmFtZSI6ImphY2sifQ.esdckJSoFhqS23tbhKNOaCrh0Gm3a0z1uCPSivTCtUc
{'id': 2, 'name': 'jack'}
'''

# PyJWT 使用

# 使用 HS256 编码和解码令牌

import jwt
key = "secret"  # 此字段可以修改成自定义的字符串
encoded = jwt.encode({"some": "payload"}, key, algorithm="HS256")
print(encoded)
jwt.decode(encoded, key, algorithms="HS256")
'''
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U
{'some': 'payload'}
'''

# 指定其他标头

token = jwt.encode(
    {"some": "payload"},
    "secret",
    algorithm="HS256",
    headers={"kid": "230498151c214b788dd97f22b85410a5"},
)
print(token)
print(jwt.decode(token, 'secret', "HS256")) # 这里并没有解码出 headers 中的信息
"""
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJzb21lIjoicGF5bG9hZCJ9.gdQ884yjlnLnIrYjfQaClE6rJC2x8v2OP2s_eXOLhZA
{'some': 'payload'}
"""

# 未经验证即可读取标头

这里的标头即上面的 headers

某些 API 要求您在未经验证的情况下读取 JWT 标头。例如,在令牌颁发者使用多个密钥的情况下,您无法事先知道颁发者的哪个公钥或共享机密用于验证,则颁发者可能会在标头中包含密钥的标识符。

jwt.get_unverified_header(encoded)
# {'alg': 'RS256', 'typ': 'JWT', 'kid': 'key-id-12345...'}

# Registered Claim Names

JWT 规范定义了一些已注册的声明名称,并定义了应如何使用它们。PyJWT 支持以下注册声明名称:

  • “exp” (Expiration Time) Claim
  • “nbf” (Not Before Time) Claim
  • “iss” (Issuer) Claim
  • “aud” (Audience) Claim
  • “iat” (Issued At) Claim

# Expiration Time Claim (exp) 到期时间声明

“exp”(到期时间)声明标识了到期时间,此时或之后不得接受 JWT 进行处理。处理 “exp” 索赔要求当前日期 / 时间必须早于 “exp” 索赔中列出的到期日期 / 时间。实现者可以提供一些小的回旋余地,通常不超过几分钟,以考虑时钟偏差。其值必须是包含 “数字日期” 值的数字。此声明的使用是可选的。

您可以将过期时间作为 UTC UNIX 时间戳(整数)或日期时间传递,后者将转换为整数。例如:

from datetime import timezone
from datetime import datetime
jwt.encode({"exp": 1371720939}, "secret")
jwt.encode({"exp": datetime.now(tz=timezone.utc)}, "secret")

过期时间在 jwt.decode() 中自动验证并引发 jwt.ExpiredSignatureError 。过期签名如果过期时间是过去,则为错误:

try:
    jwt.decode("JWT_STRING", "secret", algorithms=["HS256"])
except jwt.ExpiredSignatureError:
    # Signature has expired
    ...

过期时间将与当前 UTC 时间进行比较(由时间 timegm(datetime.now(tz=timezone.utc).utctimetuple()) 给出),因此请确保在编码中使用 UTC 时间戳或日期时间。

您可以使用 options 参数中的 verify_exp 参数关闭过期时间验证。

PyJWT 还支持过期时间定义的回旋余地部分,这意味着您可以验证过去但不是很远的过期时间。例如,如果您有一个 JWT 有效负载,其过期时间设置为创建后 30 秒,但您知道有时您将在 30 秒后处理它,则可以设置 10 秒的回旋余地以获得一些余量:

jwt_payload = jwt.encode(
    {"exp": datetime.now(tz=timezone.utc) + datetime.timedelta(seconds=30)},
    "secret",
)
time.sleep(32)
# JWT payload is now expired
# But with some leeway, it will still validate
jwt.decode(jwt_payload, "secret", leeway=10, algorithms=["HS256"])

可以使用 datetime.timedelta 实例,而不是将 leeway 指定为秒数。上面示例中的最后一行等效于

jwt.decode(
    jwt_payload, "secret", leeway=datetime.timedelta(seconds=10), algorithms=["HS256"]
)

目前尝试时, leeway 参数已经不能使用了

pay_load = {
    'id': 1,
    'name': 'jack'
}
import datetime
jwt_payload = jwt.encode(
    {"exp": datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(seconds=2), "id": 1, "name": 'jack'},
    "secret",
)
import time
time.sleep(3)
print(jwt_payload)
try:
    print(jwt.decode(jwt_payload, 'secret', algorithms="HS256"))
except jwt.ExpiredSignatureError:
    print("token过期了")
'''
如果没有过期,则输出:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NjMzMTM5ODEsImlkIjoxLCJuYW1lIjoiamFjayJ9.Jb2KPgFvHTskacJcXPxb3bH_3xKxLq126z5v6_-dl9E
{'exp': 1663313981, 'id': 1, 'name': 'jack'}
'''