jwt json web token
签发----登录成功后签发
认证---需要登录才能访问的接口,通过认证才能继续操作
2 原理-----jwt和session,cookie区别
2.1cookies
2.2 session
2.2.1sessionmiddleware
2.3 jwt
tooken长什么样?
三段式,用.分割
每段b64编码
1st段:公司信息, 加密方式 就是jwt,一般固定
2nd段:荷载payload :一般放:登录用户信息(如用户名,用户id,过期时间。签发时间,是否超级用户)
3rd段:签名singature二进制数据
签发阶段:by头部和荷载使用某种加密方式get
校验阶段:拿到token,取出第1、2部分,通过之前同样的加密方式得到新签名,
比较: 一样 信任
不同 危险
jwt实现了不在后端存储,但安全
3jwt开发重点,签发(登录接口),校验(认证类逻辑)
4.simple_jwt使用(djangorestframework_simplejwt)
django:simple_jwt, django-rest-framework-jwt(不用了,老)
flask:flask-jwt-extend
登陆签发:默认使用auth的user表--》创建个用户--》能登录了
路由: 登陆接口了
path('login/', token_obtain_pair),
# 127.0.0.1:8080/app01/login-->post--》用户名密码就能登陆
- 认证
class UserTokenView(GenericViewSet, mixins.CreateModelMixin):
# 必须登陆后才能新增
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
5.simple_jwt配置文件
要在app注册,不然不做国际化
登录后,返回两token
1:refresh
2:access(用这个)
exp过期时间,iat签发时间
exp-iat=过期时长(单位秒)
5.1.1simple_jwt配置文件(源码有)
默认配置文件
# JWT配置
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), # Access Token的有效期
'REFRESH_TOKEN_LIFETIME': timedelta(days=7), # Refresh Token的有效期
# 对于大部分情况,设置以上两项就可以了,以下为默认配置项目,可根据需要进行调整
# 是否自动刷新Refresh Token
'ROTATE_REFRESH_TOKENS': False,
# 刷新Refresh Token时是否将旧Token加入黑名单,如果设置为False,则旧的刷新令牌仍然可以用于获取新的访问令牌。需要将'rest_framework_simplejwt.token_blacklist'加入到'INSTALLED_APPS'的配置中
'BLACKLIST_AFTER_ROTATION': False,
'ALGORITHM': 'HS256', # 加密算法
'SIGNING_KEY': settings.SECRET_KEY, # 签名密匙,这里使用Django的SECRET_KEY
# 如为True,则在每次使用访问令牌进行身份验证时,更新用户最后登录时间
"UPDATE_LAST_LOGIN": False,
# 用于验证JWT签名的密钥返回的内容。可以是字符串形式的密钥,也可以是一个字典。
"VERIFYING_KEY": "",
"AUDIENCE": None,# JWT中的"Audience"声明,用于指定该JWT的预期接收者。
"ISSUER": None, # JWT中的"Issuer"声明,用于指定该JWT的发行者。
"JSON_ENCODER": None, # 用于序列化JWT负载的JSON编码器。默认为Django的JSON编码器。
"JWK_URL": None, # 包含公钥的URL,用于验证JWT签名。
"LEEWAY": 0, # 允许的时钟偏差量,以秒为单位。用于在验证JWT的过期时间和生效时间时考虑时钟偏差。
# 用于指定JWT在HTTP请求头中使用的身份验证方案。默认为"Bearer"
"AUTH_HEADER_TYPES": ("Bearer",),
# 包含JWT的HTTP请求头的名称。默认为"HTTP_AUTHORIZATION"
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
# 用户模型中用作用户ID的字段。默认为"id"。
"USER_ID_FIELD": "id",
# JWT负载中包含用户ID的声明。默认为"user_id"。
"USER_ID_CLAIM": "user_id",
# 用于指定用户身份验证规则的函数或方法。默认使用Django的默认身份验证方法进行身份验证。
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
# 用于指定可以使用的令牌类。默认为"rest_framework_simplejwt.tokens.AccessToken"。
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
# JWT负载中包含令牌类型的声明。默认为"token_type"。
"TOKEN_TYPE_CLAIM": "token_type",
# 用于指定可以使用的用户模型类。默认为"rest_framework_simplejwt.models.TokenUser"。
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
# JWT负载中包含JWT ID的声明。默认为"jti"。
"JTI_CLAIM": "jti",
# 在使用滑动令牌时,JWT负载中包含刷新令牌过期时间的声明。默认为"refresh_exp"。
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
# 滑动令牌的生命周期。默认为5分钟。
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
# 滑动令牌可以用于刷新的时间段。默认为1天。
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
# 用于生成access和刷refresh的序列化器。
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
# 用于刷新访问令牌的序列化器。默认
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
# 用于验证令牌的序列化器。
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
# 用于列出或撤销已失效JWT的序列化器。
"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",
}
###5.1.2simple_jwt在项目中配置(参考rest-framework)
from datetime import timedelta
SIMPLE_JWT ={
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), # Access Token的有效期
'REFRESH_TOKEN_LIFETIME': timedelta(days=7), # Refresh Token的有效期
"AUTH_HEADER_TYPES": ("TOKEN",),
}
6定制登录后的返回格式
原来返回
原来使用
6.1自己写个序列化类
settings.py的最后一行
'TOKEN_OBTAIN_SERIALIZER':'app01.serializer.CommonTokenObtainSerializer'
serialier.py
{
"code": 100,
"msg": "登录成功",
"username": "lqz",
"refresh": "",
"access": ""
}
前端看到
{
"code": 100,
"msg": "登录成功",
"username": "lqz",
"refresh": "",
"access": ""
}
也可以把user信息放到荷载里面
对荷载b64解码就能看到自己加进去的username,这样,就不需要在自己定制的返回格式里面加
补充base64
-
(长度一定是4的倍数,如果不是,用等号补齐,后面最多3个等号)
是编码方式,不是加密 作用 1.网络传输----字符串编码成base64 2.图片用b64传给前端 3.jwt使用
如果是b64图片,可以这么保存,解码出来是bytes格式,可以直接写入到文件,wb模式