JWT的简析

JWT概念:

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

基于token的鉴权机制
token由3部分组成

  1. jwt的头部承载两部分信息:
    声明类型,这里是jwt
    声明加密的算法 通常直接使用 HMAC SHA256
    对头部进行base64加密,构成第一部分

  2. payload
    载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分
    标准中注册的声明
    公共的声明
    私有的声明

    公共的声明 : 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

    私有的声明 : 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

  3. signature
    JWT的第三部分是一个签证信息,这个签证信息由三部分组成:
    header (base64后的)
    payload (base64后的)
    secret
    这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

    注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证
    JWT的简析
    token作为保存状态的一种方式,原理流程如图
    1.用户注册或登录时使用用户名和密码来请求服务器
    2 服务器验证用户名密码无误后,经过加密算法构造出一个token值
    3 服务器将生成的token值签发给用户,客户端会存储这个token值
    4 客户端每次发起请求登录服务器时,都会携带token值,服务器会拿到客户端请求头里的header和payload再次进行计算得出token两者进行比较来判断是否原用户

优点:
因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。

便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
它不需要在服务端保存会话信息, 所以它易于应用的扩展

WTF在DRF框架中的使用:

官方文档:Django REST framework.

  1. 虚拟环境中安装
pip install djangorestframework-jwt
  1. 配置
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),  # 有效期
}
  1. 使用
    Django REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

签发的token值可以作为用户对象的一个属性,进行序列化输出给客户端用户
user.token = token