pip install PyJWT
# JWT官网的三个加密参数为
# 1.header(type,algorithm)
# {
# "alg": "HS256",
# "typ": "JWT"
# }
# 2.playload(iss,sub,aud,exp,nbf,lat,jti)
# iss: jwt签发者
# sub: jwt所面向的用户
# aud: 接收jwt的一方
# exp: jwt的过期时间,这个过期时间必须要大于签发时间
# nbf: 定义在什么时间之前,该jwt都是不可用的.
# iat: jwt的签发时间
# jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
# 3.signature
# jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
# header (base64后的)
# payload (base64后的)
# secret
# PyJwt官网的三个加密参数为
# jwt.encode(playload, key, algorithm='HS256')
# playload 同上,key为SECRET_KEY,algorithm 为加密算法
import jwt
from jwt import ExpiredSignatureError
from pytz import timezone
secret = "f7aa59c6-fd5d-407b-862b-f4d2d2ecf0de"
issuer = "General_zy"
audience = "user"
def encode_token():
import datetime
# 这里需要指明时区为Asia/Shanghai,否则token会+8:00
now = datetime.datetime.now(tz=timezone('Asia/Shanghai'))
dic = {
# 过期时间
'exp': now + datetime.timedelta(seconds=5),
# 签发时间
'iat': now,
# 签发方
'iss': issuer,
# 接收人
"aud": audience,
}
token_bytes = jwt.encode(dic, key=secret, algorithm='HS256')
return token_bytes.decode("utf-8")
def decode_token(token):
if isinstance(token, str):
token = token.encode("utf-8")
# 解密,校验签名
try:
payload = jwt.decode(token, key=secret, issuer=issuer, audience=audience, algorithms=['HS256'])
return payload
except ExpiredSignatureError as e:
print(f"token过期:{str(e)}")
return None
except Exception as e:
print(f"其他错误:{str(e)}")
if __name__ == '__main__':
# 1. 生成token
# eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzQyMDU4NzcsImlhdCI6MTY3NDIwNTg3MiwiaXNzIjoiR2VuZXJhbF96eSIsImF1ZCI6InVzZXIifQ.O_LUfOP4fXnFsRgGZrCEjxW8nD5WB3s8WBXNsUsIqTo
print(encode_token())
# 2. 解码token
data = decode_token("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzQyMDU4NzcsImlhdCI6MTY3NDIwNTg3MiwiaXNzIjoiR2VuZXJhbF96eSIsImF1ZCI6InVzZXIifQ.O_LUfOP4fXnFsRgGZrCEjxW8nD5WB3s8WBXNsUsIqTo")
print(data)
exp
exp指过期时间,在生成token时,可以设置该token的有效时间,如果设置1天过期,1天后再解析此token会抛出
jwt.exceptions.ExpiredSignatureError: Signature has expired
nbf
nbf类似于token的 lat ,它指的是该token的生效时间,如果使用但是没到生效时间则抛出
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)
iss
iss指的是该token的签发者,可以给一个字符串。iss 在接收时如果不检验也没有问题,如果接收时需要检验但是又签名不一致,则会抛出
jwt.exceptions.InvalidIssuerError: Invalid issuer
aud
aud指定了接收者,接收者在接收时必须提供与token要求的一致的接收者(字符串),如果没写接收者或者接收者不一致会抛出
jwt.exceptions.InvalidAudienceError: Invalid audience
iat
iat指的是token的开始时间,如果当前时间在开始时间之前则抛出
jwt.exceptions.InvalidIssuedAtError: Issued At claim (iat) cannot be in the future.
pip install djangorestframework-simplejwt
# 需要在django配置的关键字为"SIMPLE_JWT"
USER_SETTINGS = getattr(settings, "SIMPLE_JWT", None)
# 默认配置
DEFAULTS = {
# 访问令牌的有效时间
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
# 刷新令牌的有效时间
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
# 若为True,则刷新后新的refresh_token有更新的有效时间
"ROTATE_REFRESH_TOKENS": False,
# 若为True,刷新后的token将添加到黑名单中
# When True,'rest_framework_simplejwt.token_blacklist',should add to INSTALLED_APP
"BLACKLIST_AFTER_ROTATION": False,
"UPDATE_LAST_LOGIN": False,
# 加密算法
"ALGORITHM": "HS256",
# 加密密钥
"SIGNING_KEY": settings.SECRET_KEY,
"VERIFYING_KEY": "",
"AUDIENCE": None,
"ISSUER": None,
"JSON_ENCODER": None,
"JWK_URL": None,
"LEEWAY": 0,
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
"USER_ID_FIELD": "id",
"USER_ID_CLAIM": "user_id",
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
"JTI_CLAIM": "jti",
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 自己的应用
...
'rest_framework', # 注册DRF应用
]
# simplejwt配置, 需要导入datetime模块
SIMPLE_JWT = {
# token有效时长
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30),
# token刷新后的有效时间
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication', # 使用rest_framework_simplejwt验证身份
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated' # 默认权限为验证用户
],
}
# urls.py
from django.contrib import admin
from django.urls import path, include
# 导入 simplejwt 提供的几个验证视图类
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
urlpatterns = [
# Django 后台
path('admin/', admin.site.urls),
# DRF 提供的一系列身份认证的接口,用于在页面中认证身份。
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
# 获取Token的接口
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
# 刷新Token有效期的接口
path('api/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
# 验证Token的有效性
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]
在这里插入代码片