jwt组件
cookie,session,token
cookie
服务器端产生,保存不重要或认证信息,保存在客户端
session
服务器端产生,保存登录信息等重要信息,保存在服务端
token
服务端产生,保存认证信息,保存在客户端的cookie中
优点
- 数据库不需要存储token,所以服务器的IO操作会减少(只有IO读,没有IO写)
- 服务器端只存储token的签发和校验算法,执行效率高.
- 签发与校验算法在多个服务器上可以统一,在架设机群的情况下也可以完美完成高效的签发和校验,
突破点
- token必须要有多个部分组成,其中包含可以反解的部分和不可以反解的部分,--jwt采用三段式
- token中必须含有过期时间,用来保证token的安全性和时效性
jwt认证规则
json web token认证
基本原理:第一次认证通过用户名和密码,服务端签发一个json的token,后续客户端的请求都带着这个token,服务端解析这个token来判断客户端的身份和合法性.
组成
jwt由,头,载荷,和签名三部分组成,各部分间通过.
来分割,每一部分都是一个json字典,头和载荷采用了base64可逆加密算法加密,签名采用HS256不可逆加密算法加密.
内容
头header
基本信息:可逆与不可逆的加密算法,公司名称,项目组信息,开发者信息等
{
"company":"ali",
"algorithm":"base64";
...
}
载荷payload
核心信息:用户主键,用户账号,客户端设备信息,过期时间等,官方建议但是非必须
{
"pk":1,
...
}
签名signature
安全信息:头的加密结果,载荷的加密结果,服务器的安全码(盐)等
{
"header":"...",
...
}
签发算法
-
头内容:
写死(可以为空):公司,项目信息,都是固定不变的
=> 将数据字典转化为json格式字符串,再将json字符串加密为base64字符串
-
载荷的内容:
用户账号,客户端设备信息由客户端提供,用户名,主键等要验证信息,过期时间以及刷新时间
=> 将数据字典转化为json格式字符串,再将json字符串加密为base64字符串
-
签名的内容:
将头的加密结果,载荷的加密结果,再从服务器上拿到安全码,也可以包含额外的载荷部分(用户信息,设备信息)
=> 将数据字典转化成json字符串,再将json字符串加密为HS256字符串
-
将三个字符串使用
.
连接称为三段式token
校验算法
- 从客户端提交的请求中获取token,使用
.
分割成三段 - header头(第一部分)可以不解密
- payload载荷(第二部分)一定要解密,先使用base64解密成json字符串,再转换为字典数据格式
- 用户主键与用户账号查询User表确定用户是否存在
- 设备信息与本次提交的设备信息比对,确定前后是否为统一设备提交,决定是否对用户做安全提示(异地登录信息)
- 过期时间校验,看该token是否在有效时间内
- signature签名(第三段)采用加密碰撞校验
- 将头,载荷加密字符串和数据库安全码形成json字典,转成成json字符串.
- 采用不可逆HS256加密形成加密字符串
- 新的加密字符串与发过来的token中的第三段碰撞对比,一致才能保证token是合法的.
- 校验算法通过后,载荷校验得到User对象,就是该token代表的登录用户(Django项目一般会把登录用户存放在request.user中)
刷新算法
-
在签发token的载荷中,添加第一次签发token的时间,和刷新有效时间
(比如一小时刷新一次token,那么这一小时之内的访问就不需要签发新的token,而token的过期时间为一周,那么一小时之外一周之内的时间段内就需要不断刷新token,一直到过期时间后token失效)
-
每一次请求携带token,不仅走校验算法验证token是否合法,还要额外请求刷新token接口,如果超过刷新时间,则签发新的token,整体过期时间后移.(没有超过过期时间,产生新的token给客户端,超过了,刷新失败)
-
服务端要同时设置过期时间,还要设置刷新时间.
Python使用
安装
$ pip install djangorestframework-jwt
配置
settings中
import datetime
JWT_AUTH = {
# 过期时间
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
# 是否允许刷新
'JWT_ALLOW_REFRESH': True,
# 最大刷新时间
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}