当前位置: 首页 > web >正文

JWT令牌

1. JWT概述

JWTJSON Web Token,是一个开放标准,用于在各方之间安全地传输信息。并且JWT经过数字签名,安全性高。通俗来说,也就是以JSON形式作为Web应用中的令牌,用于信息传输,在数据传输过程中可以完成数据加密、签名等相关处理。

JWT由于其简洁、自包含和易于验证的特性,被广泛应用于各种场景,尤其是在分布式系统中:

  • 身份验证 Authentication):这是JWT最常见的用途。当用户成功登录后,服务器会返回一个JWT给客户端。客户端将JWT存储起来,并在后续的每个请求中携带JWT。服务器通过验证JWT,可以确认用户的身份,而无需依赖传统的SessionCookie机制,这对于构建无状态的RESTful API非常有用。
  • 授权 Authorization:一旦用户通过身份验证,JWT还可以用于授权。Payload中可以包含用户的角色、权限等信息。服务器在接收到客户端的请求后,可以通过解析JWT中的这些信息,判断用户是否有权限访问特定的资源或执行特定的操作。
  • 信息交换 Information ExchangeJWT可以在各方之间安全地传输信息。由于JWT可以被签名并且加密,因此可以确保信息的完整性和机密性。例如,在微服务架构中,不同的服务之间可以使用JWT来传递用户身份信息或其他安全相关的声明。
  • 单点登录 Single Sign-On, SSOJWT可以方便地实现SSO。当用户在一个应用中登录后,认证服务器可以生成一个包含用户身份信息的JWT,其他信任该认证服务器的应用可以通过验证这个JWT,实现用户的免登录访问。
  • 无状态的API:传统的Session机制需要在服务器端存储用户的会话信息,这在用户量大或者需要水平扩展的场景下会带来挑战。JWT是自包含的,所有的状态都存储在Token本身,服务器不需要维护会话存储,从而更容易实现无状态的 API 和服务的扩展。
  • 移动应用认证 Mobile App AuthenticationJWT非常适合移动应用与后端服务器之间的身份验证。由于JWT本身就是一个字符串,可以方便地通过HTTP Header或其他方式传递,而不需要依赖浏览器特定的Cookie机制。
  • 安全地传递临时凭证 Securely Passing Temporary Credentials:例如在用户找回密码的流程中,可以生成一个包含临时凭证和过期时间的JWT,通过邮件发送给用户。用户点击链接后,服务器验证JWT的有效性,并允许用户重置密码。

总而言之,JWT是一种强大且灵活的安全令牌,广泛应用于现代Web应用和分布式系统中,用于解决身份验证、授权和安全信息传输等问题。

2. Session认证

Session认证是一种基于服务端会话管理的身份验证机制,主要用于跟踪用户的登录状态。其核心流程如下:

  • 会话初始化:用户首次登录时,服务端验证用户名和密码后,生成唯一Session ID,并将用户数据如用户ID、权限存储在服务端内存或数据库中。
  • 凭证传递:服务端通过HTTP响应头的Set-Cookie字段将Session ID发送至客户端,浏览器自动将其保存为Cookie
  • 会话维持:客户端后续请求时,浏览器自动携带Cookie中的Session ID。服务端通过该ID查询会话存储,验证用户身份和权限。

该方式可以很好的解决身份验证的问题,但是同时也暴露了以下问题:

  • 每个用户经过应用验证之后,都需要在服务器做保存会话记录,通常来说session都是保存在内存中的,随着认证用户越多,服务端的开销也会越来越大。
  • 在分布式环境下需要同步存储【session共享】,限制了负载均衡器的能力,也限制了应用的扩展能力。
  • 基于Cookie来进行用户识别,cookie如果被截获,用户很容易遭受跨站请求伪造的攻击。
    • xss攻击:跨站脚本攻击,通过向网页注入恶意脚本,利用浏览器信任机制在用户端执行攻击代码的安全漏洞。攻击者可通过注入的脚本窃取用户敏感信息如Cookie、会话令牌或劫持用户操作。
    • xsrf攻击:利用用户已登录的身份,诱导其点击恶意链接或访问含恶意请求的页面,以用户名义执行非授权操作,如转账、修改密码。
  • 在前后端分离项目中,部署困难。

为了解决以上问题,可以使用Token认证,如JWT认证。

3. JWT认证

3.1 JWT原理

一个JWT是一个由三部分组成的字符串,这三部分之间用点 .分隔。如下:

  • Header头部:通常包含以下两部分:Header会经过Base64Url编码形成JWT的第一部分。这方便之后的解码。

    • typtoken的类型,对于JWT来说,就是JWT
    • alg:签名算法,如HS256RSA
  • Payload载荷:Payload也会经过Base64Url 编码形成JWT 的第二部分。Payload是未加密的,不要在其中放入敏感信息。

    • 包含claims声明,是关于实体和其它数据的声明。
    • Payload中可以包含三种类型的claims
      • Registered claims注册声明:这是一组预定义的声明,不是强制性的,但推荐使用,例如:
        • issJWT 的签发者。
        • subJWT 的主题。
        • audJWT 的接收方。
        • expJWT的过期时间。
        • nbf :在此时间之前,JWT 不可用。
        • iatJWT 的签发时间。
        • jtiJWT 的唯一标识符。
      • Public claims 公共声明:可以由JWT的使用者自定义,但为了避免冲突,应该在 IANA JSON Web Token Registry 中注册。
      • Private claims私有声明:由生成和使用 JWT 的双方自定义的声明,用于传递自定义信息。
  • Signature签名:用于验证 JWT 的完整性和真实性,签名是基于 HeaderPayload,使用 Header 中指定的签名算法以及一个secret 密钥生成的。

    HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
    

总的来说,JWT的生成和验证流程如下:

  • 生成JWT

    • 服务器接收到用户的登录请求并验证凭据。如果验证成功,服务器会创建一个包含用户身份信息和其他必要信息的Payload

    • 服务器选择一个签名算法,并使用该算法、Payload和一个只有服务器知道的Secret KeyHeaderPayload进行签名。

    • HeaderPayloadSignature经过Base64Url编码后用 . 连接起来,形成最终的JWT

    • 服务器将JWT返回给客户端。

  • 使用JWT进行身份验证:

    • 客户端在后续的HTTP请求中,通常通过Authorization请求头携带JWT

    • 服务器接收到请求后,会提取JWT

    • 服务器对JWTHeaderPayload进行Base64Url解码。

    • 服务器使用相同的签名算法和Secret Key,对解码后的HeaderPayload重新计算签名。服务器将重新计算的签名与JWT中包含的Signature进行比较。如果签名一致,则说明JWT没有被篡改,并且是由服务器颁发的。

    • 服务器还会验证Payload中的声明,例如 exp ,以确保JWT仍然有效。

    • 如果验证通过,服务器就认为客户端是经过身份验证的,并根据JWT中包含的信息授予相应的访问权限。

相较于传统的Session相比,JWT有以下优势:

  • 无状态:Session机制需要在服务端存储用户的会话信息,但是JWT是自包含的,用户的状态信息都存储在Token本身【payload中】,且该Token存储在客户端。这样就降低了服务器的压力,提高性能。
  • 可扩展性:不同的服务之间可以共享相同的密钥来验证JWT,而无需共享Session存储或进行跨服务的Session查询,很适合分布式应用。这降低了服务之间的耦合性,提高系统的可扩展性。
  • 跨域/跨平台:传统的Session跨域请求时可能会受到限制,如何浏览器的同源策略。JWT作为一个独立的Token字符串,可以方便的通过请求头Authorization或请求体在不同的域或平台传递,具有更好的跨域和跨平台兼容性。
  • 更适合移动应用:移动应用通常不依赖浏览器的Cookie机制来管理SessionJWT可以很方便的存储在移动应用的本地存储中,并通过自定义请求头发送给服务器,与后端api进行身份验证。

4. 代码实现

import time# Create your tests here.
import jwt
import datetimedef create_token(secret_key, user_id, username, exp=10):"""生成JWT令牌"""# 定义payloadpayload = {'user_id': user_id,'username': username,# 设置过期时间'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=exp),# jwt的签发时间'iat': datetime.datetime.utcnow()}token = jwt.encode(payload, secret_key, algorithm='HS256')return tokendef verify_token(token, secret_key):"""验证JWT令牌"""try:payload = jwt.decode(token, secret_key, algorithms=['HS256'])print("JWT OK")except jwt.ExpiredSignatureError:print("JWT has expired")return Noneexcept jwt.InvalidSignatureError:print("Invalid JWT signature")return Noneexcept jwt.DecodeError:print("Invalid JWT format")return Noneif __name__ == '__main__':# 安全密钥SECRET_KEY = 'ashkjfhaafjh+@@safdnsjkf'user = {'id': 1,'username': 'admin'}# 生成JWT令牌token = create_token(SECRET_KEY, user['id'], user['username'])# 验证JWT令牌payload1 = verify_token(token, SECRET_KEY) # JWT OKtime.sleep(12)payload2 = verify_token(token, SECRET_KEY) # JWT has expired
http://www.xdnf.cn/news/6842.html

相关文章:

  • 记一次从windows连接远程Linux系统来控制设备采集数据方法
  • 武器装备论证全流程分析
  • GDB 高级调试技术深度解析
  • 自定义类型-结构体传参
  • 京东方10.1寸工业液晶屏GV101WXM-N80
  • 【在aosp中,那些情况下可以拉起蓝牙服务进程】
  • 道路运输企业管理人员考试真题练习
  • Shotcut:免费开源的视频编辑利器
  • [特殊字符] Maven配置阿里云镜像终极指南(2024最新版)
  • DevExpressWinForms-GridControl-无限滚动
  • “数据类型与OOP核心”的一些问题
  • 团队模式总结
  • python第二十七天
  • 吉客云数据集成到金蝶云星空的最佳实践
  • ai agent(智能体)开发 python高级应用4:什么是代理,如何设置squid代理服务器,让crawl4ai 0.6.3 用上代理,获取到数据平权
  • MySQL中表的增删改查(CRUD)
  • 【Win32 API】 lstrcpyA()
  • Python3.12之解决:externally-managed-environment问题(二十九)
  • 薄膜压力传感器主要应用场景
  • STM32外设AD-轮询法读取模板
  • 系统架构设计师案例分析题——web篇
  • 软考 系统架构设计师系列知识点之杂项集萃(61)
  • vue.js中的列表过滤+排序
  • Qt窗口中消除边框的解决方法
  • DAY24元组和OS模块
  • 【mysql】并发 Insert 的死锁问题 第二弹
  • Spring actuator
  • SQLMesh 增量模型从入门到精通:5步实现高效数据处理
  • 云、边、端
  • Echart设置圆饼图pie中间文字排版