• 聊聊 JSON Web Token (JWT) 和 jwcrypto 的使用


    哈喽大家好,我是咸鱼。

    最近写的一个 Python 项目用到了 jwcrypto 这个库,这个库是专门用来处理 JWT 的,JWT 全称是 JSON Web Token ,JSON 格式的 Token。

    今天就来简单入门一下 JWT。

    官方介绍:https://jwt.io/introduction

    先聊聊 Token

    Token 的意思是令牌,通常用于身份验证。

    例如,当客户端首次登录服务器时,服务器会生成一个 Token 并返回给客户端。此后,客户端只需在请求数据时带上这个 Token,无需再次提供用户名和密码。

    为什么要有 Token ?

    我们知道 HTTP 请求是无状态的,也就是说服务器无法识别每个请求的发起者(例如,我登录淘宝网后刷新页面,会要求我重新输入用户名和密码进行登录)。

    为了解决这个问题,出现了一种解决方案:即服务器为每个客户端分配一个 session。当客户端发起请求时带上这个 session,服务器就能识别请求的发起者。

    然而,这种方法很快暴露了一些弊端。首先是开销问题。服务器需要保存所有客户端的 session,如果访问的客户端数量增加,服务器将需要保存成千上万个 session,带来巨大的存储开销。

    其次是跨域问题。例如,在集群架构中有两台服务器 A 和 B。如果咸鱼第一次请求到了 A 服务器,A 服务器保存了咸鱼的 session,但如果下一次请求被分配到 B 服务器,B 服务器上没有咸鱼的 session,该怎么办?

    一种解决方案是使用 session 粘滞(session sticky)方法,使咸鱼的每次请求都打到同一个服务器(如 A 服务器)。但如果 A 服务器宕机了,请求就不得不转到 B 服务器,依然无法解决问题。

    于是,有人提出了另一种思路:为什么要让服务器保存 session 呢?可以让每个客户端自己保存!服务器只负责生成 session,不负责保存。

    但是,如果不保存 session,如何区分客户端?又如何验证 session 是服务器生成的呢?

    这时,人们想到了让服务器生成一个 token。这个 token 是通过服务器独有的密钥和算法(例如 RS256 算法)生成的,并且服务器不会保存这个 token。

    这样,客户端发起请求时带上这个 token,服务器收到后会用相同的算法和密钥进行验证。如果 token 匹配,服务器就能验证客户端的身份。

    再聊聊 JWT

    简单介绍了 token,我们来看看 JWT。

    JWT(JSON Web Token)是一种在网络中以 JSON 格式安全地传输信息的令牌。其原理是:服务器认证之后,生成一个 JSON 格式的 token,并将其发回给用户,类似下面这样:

    {
      "alg": "RSA",
      "name": "咸鱼",
      "role": "管理员",
      "exp": "2024-05-20T00:00:00Z"
    }
    

    之后客户端与服务器通信的时候都通过这个 JSON Token 来验证身份,同时为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

    优点:

    • 紧凑性:JWT 被设计成体积较小,便于 URL、POST 参数或 HTTP 头部传输。
    • 自包含:JWT 负载中包含所有必要的信息,不需要在每次请求时访问数据库。
    • 安全性:JWT 可以签名(使用 HMAC 或 RSA 算法),确保数据的完整性和真实性。通过加密(例如 JWE)还可以保证数据的机密性。

    结构组成:

    JWT 由 Header、Payload、Signature(签名) 三部分组成,其中 Header 和 Payload 都是 JSON 格式( JWT 中的 J ):

    • Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
    • Payload : 用来存放实际需要传递的数据
    • Signature(签名):服务器通过 Payload、Header 和一个密钥 (Secret) 使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。

    编码之后的 JWT 形式是一个很长的字符串,中间用点(.)分隔成三个部分,写成一行(里面没有换行),类似下面这样:

    Header.Payload.Signature
    

    关于 JWT 三部分的内容就不多讲了,官网有详细介绍。

    jwcrypto 使用

    我们可以使用 Python 的 jwcrypto 库来生成和验证 JWT、加密和解密数据,以及签名和验证签名等操作。

    jwcrypto 提供了一系列功能,包括但不限于:

    • 生成和验证 JWT:可以使用 jwcrypto 生成 JWT,并在接收端验证 JWT 的有效性。
    • 加密和解密数据:支持使用不同的算法对数据进行加密和解密,例如 AES、RSA 等。
    • 签名和验证签名:支持使用不同的算法对数据进行签名,并在接收端验证签名的有效性。
    • 密钥管理:支持生成和管理密钥对、公钥和私钥,以及密钥的导入和导出。

    安装 jwcrypto

    pip install jwcrypto
    

    生成一个带有签名的 JWT,其中包含了指定的用户 ID:

    from jwcrypto import jwt,jwk
    
    # 使用 RSA 算法生成一个 2048 位的密钥对。
    key = jwk.JWK.generate(kty='RSA', size=2048)
    payload = {'user_id': 123}
    
    # 创建一个 JWT 对象,并指定其头部(header)为使用 RS256 算法进行签名。
    token = jwt.JWT(header={'alg': 'RS256'}, claims=payload)
    
    # 使用之前生成的密钥对 JWT 进行签名。
    token.make_signed_token(key)
    

    生成 RSA 密钥对并导出公私钥:

    from jwcrypto import jwk
    
    # 生成 RSA 密钥对
    key = jwk.JWK.generate(kty='RSA', size=2048)
    
    # 导出公钥和私钥
    public_key = key.export_public()
    private_key = key.export_private()
    
    # 打印公钥和私钥
    print("公钥:")
    print(public_key)
    print("\n私钥:")
    print(private_key)
    
  • 相关阅读:
    转载:丰子恺迭浪式阅读法
    简述React 和 Vue 的 diff 时间复杂度从 O(n^3) 优化 到 O(n) ,那么 O(n^3) 和 O(n) 是如何计算出来的 ?
    Aeron:Online Resources
    建立Line类
    C高级第2天
    入门力扣自学笔记117 C++ (题目编号761)
    LeetCode第206题—反转链表
    【文献导读】XPBD: Position-Based Simulation of Compliant Constrained Dynamics
    数据库公共字段自动填充
    《设计模式之美》第四章 总结
  • 原文地址:https://www.cnblogs.com/edisonfish/p/18202633