jwt 揭秘

jwt(JSON Web Tokens),是一种开发的行业标准 RFC 7519 ,用于安全的表示双方之间的声明。目前,jwt广泛应用在系统的用户认证方面,特别是现在前后端分离项目。

1. jwt认证流程!

在项目开发中,一般会按照上图所示的过程进行认证,即:用户登录成功之后,服务端给用户浏览器返回一个token,以后用户浏览器要携带token再去向服务端发送请求,服务端校验token的合法性,合法则给用户看数据,否则,返回一些错误信息。

传统token方式和jwt在认证方面有什么差异?

  • 传统token方式

    用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。
    
  • jwt方式

    1.用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端接收到token之后,通过jwt对token进行校验是否超时、是否合法。
    

2. jwt创建token

2.1 原理

jwt的生成token格式如下,即:由 . 连接的三段字符串组成。

1.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

生成规则如下:

  • 第一段HEADER部分,固定包含算法和token类型,对此json进行base64url加密,这就是token的第一段。

    headers = {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • 第二段PAYLOAD部分,包含一些数据,对此json进行base64url加密,这就是token的第二段。

    payload = {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
      ...
    }
    
  • 第三段SIGNATURE部分,把前两段的base密文通过.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。

    base64url(
        HMACSHA256(
          base64UrlEncode(header) + "." + base64UrlEncode(payload),
          your-256-bit-secret (秘钥加盐)
        )
    )
    

    最后将三段字符串通过 .拼接起来就生成了jwt的token。

    注意:base64url加密是先做base64加密,然后再将 - 替代 +_ 替代 /

2.2 代码实现

基于Python的pyjwt模块创建jwt的token。

  • 安装

    1. pip3 install pyjwt
    
  • 实现

    import jwt
    import datetime
    from jwt import exceptions
    SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
    def create_token():
        # 构造header
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
        # 构造payload
        payload = {
            'user_id': 1, # 自定义用户ID
            'username': 'wupeiqi', # 自定义用户名
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5) # 超时时间
        }
        result = jwt.encode(payload=payload, key=SALT, algorithm="HS256", headers=headers).decode('utf-8')
        return result
    if __name__ == '__main__':
        token = create_token()
        print(token)
    

3. jwt校验token

一般在认证成功后,把jwt生成的token返回给用户,以后用户再次访问时候需要携带token,此时jwt需要对token进行超时合法性校验。

取token之后,会按照以下步骤进行校验:

一般在认证成功后,把jwt生成的token返回给用户,以后用户再次访问时候需要携带token,此时jwt需要对token进行超时合法性校验。

获取token之后,会按照以下步骤进行校验:

  • 将token分割成 header_segmentpayload_segmentcrypto_segment 三部分
  • 对第一部分header_segment进行base64url解密,得到header
  • 对第二部分payload_segment进行base64url解密,得到payload
  • 对第三部分crypto_segment进行base64url解密,得到signature
  • 对第三部分signature部分数据进行合法性校验
    • 拼接前两段密文,即:signing_input
    • 从第一段明文中获取加密算法,默认:HS256
    • 使用 算法+盐 对signing_input 进行加密,将得到的结果和signature密文进行比较。
import jwt
from jwt import exceptions

SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='


def get_payload(token):
    """
    根据token获取payload
    :param token:
    :return:
    """
    try:
        # 从token中获取payload【校验合法性,并获取payload】
        verified_payload = jwt.decode(token, SALT, ["HS256"])
        return verified_payload
    except exceptions.ExpiredSignatureError:
        print('token已失效')
    except jwt.DecodeError:
        print('token认证失败')
    except jwt.InvalidTokenError:
        print('非法的token')


if __name__ == '__main__':
    token = "eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Ind1cGVpcWkiLCJleHAiOjE2NDc2MjMzMDR9.mC409LXIl1RZu4OX5J01hvCxWEOJcK7C4P3zKzedXdU"
    payload = get_payload(token)
    print(payload)

4. jwt实战

4.1 django 案例

在用户登录成功之后,生成token并返回,用户再次来访问时需携带token。

此示例在django的中间件中对tokne进行校验,内部编写了两个中间件来支持用户通过两种方式传递token

  • url传参

    1.http://www.pythonav.com?token=eyJhbGciOiJIUzI1N...
    

  • Authorization请求头

    GET /something/ HTTP/1.1
    Host: pythonav.com
    Authorization: JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIj
    

4.2 django rest framework 案例

在用户登录成功之后,生成token并返回,用户再次来访问时需携带token。

此示例在drf的认证组件中对token进行校验,内部编写了两个认证组件来支持用户通过两种方式传递token。

  • url传参
  • Authorization请求头

4.3 flask 案例

在用户登录成功之后,生成token并返回,用户再次来访问时需携带token。

此示例在flask的before_request中对token进行校验,内部编写了两个函数来支持用户通过两种方式传递token。

  • url传参
  • Authorization请求头

本文作者:晚点心动。

本文链接:https://www.cnblogs.com/lucky-tao/p/16670393.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   晚点心动。  阅读(62)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 小星星 七喜
  2. 2 情深深雨濛濛 杨胖雨
  3. 3 山水之间 许嵩
  4. 4 不潮不用花钱 御小兮
  5. 5 Rage Your Dream m.o.v.e
  6. 6 Disconnected Pegboard Nerds
  7. 7 STAY The Kid LAROI,Justin Bieber
  8. 8 Sunburst Tobu,Itro
  9. 9 迪士尼在逃公主 徐秉龙
  10. 10 赴约 赵乃吉
  11. 11 Tell Me 潘玮柏,徐洁儿
  12. 12 潮汐(抖音DJ版) 涛少君
  13. 13 我只能爱你 彭青
  14. 14 喜欢你 火鸡
  15. 15 失忆 郑十一(郑毅),蔡鹤峰
  16. 16 写不完的温柔 G.E.M.邓紫棋
  17. 17 忽而今夏 就是南方凯阿
  18. 18 老男孩 仲夏夜
  19. 19 2002 J.Fla
  20. 20 ✘ 按 下 暫 停 你 將 變 的 清 醒 且 墮 落 Mei
山水之间 - 许嵩
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.