jwt组件

cookie,session,token

服务器端产生,保存不重要或认证信息,保存在客户端

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":"...",
    ...
}

签发算法

  1. 头内容:

    写死(可以为空):公司,项目信息,都是固定不变的

    => 将数据字典转化为json格式字符串,再将json字符串加密为base64字符串

  2. 载荷的内容:

    用户账号,客户端设备信息由客户端提供,用户名,主键等要验证信息,过期时间以及刷新时间

    => 将数据字典转化为json格式字符串,再将json字符串加密为base64字符串

  3. 签名的内容:

    将头的加密结果,载荷的加密结果,再从服务器上拿到安全码,也可以包含额外的载荷部分(用户信息,设备信息)

    => 将数据字典转化成json字符串,再将json字符串加密为HS256字符串

  4. 将三个字符串使用.连接称为三段式token

校验算法

  1. 从客户端提交的请求中获取token,使用.分割成三段
  2. header头(第一部分)可以不解密
  3. payload载荷(第二部分)一定要解密,先使用base64解密成json字符串,再转换为字典数据格式
    1. 用户主键与用户账号查询User表确定用户是否存在
    2. 设备信息与本次提交的设备信息比对,确定前后是否为统一设备提交,决定是否对用户做安全提示(异地登录信息)
    3. 过期时间校验,看该token是否在有效时间内
  4. signature签名(第三段)采用加密碰撞校验
    1. 将头,载荷加密字符串和数据库安全码形成json字典,转成成json字符串.
    2. 采用不可逆HS256加密形成加密字符串
    3. 新的加密字符串与发过来的token中的第三段碰撞对比,一致才能保证token是合法的.
  5. 校验算法通过后,载荷校验得到User对象,就是该token代表的登录用户(Django项目一般会把登录用户存放在request.user中)

刷新算法

  1. 在签发token的载荷中,添加第一次签发token的时间,和刷新有效时间

    (比如一小时刷新一次token,那么这一小时之内的访问就不需要签发新的token,而token的过期时间为一周,那么一小时之外一周之内的时间段内就需要不断刷新token,一直到过期时间后token失效)

  2. 每一次请求携带token,不仅走校验算法验证token是否合法,还要额外请求刷新token接口,如果超过刷新时间,则签发新的token,整体过期时间后移.(没有超过过期时间,产生新的token给客户端,超过了,刷新失败)

  3. 服务端要同时设置过期时间,还要设置刷新时间.

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),
}
posted @ 2020-01-01 22:58  Agsol  阅读(237)  评论(0编辑  收藏  举报