pyjwt和djangorestframework-simplejwt【待续】

pyJwt

安装

pip install PyJWT

JWT参数

# 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)

pyjwt和djangorestframework-simplejwt【待续】_第1张图片

参数详解

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.

djangorestframework-simplejwt

安装

pip install djangorestframework-simplejwt

simplejwt的配置文件

  1. refresh_token:用于token失效时,刷新获得新的token。
  2. access_token:就是jwt里面的token。
# 需要在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",
}

配置drf和simplejwt

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'),
]

自定义校验

在这里插入代码片

你可能感兴趣的:(python,python,开发语言)