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

API接口安全-1:身份认证之传统Token VS JWT

在Web应用开发中,身份认证是保障系统安全的核心环节。从早期的Session认证到如今的Token机制,技术不断演进以适应分布式、跨域场景的需求。其中,传统TokenJWT(JSON Web Token) 是两种主流方案,但二者在实现原理、适用场景上有显著差异。本文将分析两者的工作机制、优缺点及核心区别。

一、传统Token:依赖存储的“凭证式”认证

1. 什么是传统Token?

传统Token(令牌)是服务器颁发给客户端的“访问凭证”,本质是一串随机字符串(如UUID)。客户端通过Token证明自己的身份,服务器通过验证Token的有效性(是否存在、是否过期)决定是否允许访问资源。

2. 工作原理:“存储-校验”的中心化流程

传统Token的认证流程可概括为“生成-存储-验证”三步,核心依赖外部存储(如Redis、数据库)记录Token状态:

认证流程详解
  1. 用户登录:前端提交账号密码,服务器验证通过后,生成唯一Token(如a1b2c3d4-5678-90ef-ghij-klmnopqrstuv);
  2. 存储Token:服务器将Token作为key,用户ID(或用户信息)作为value,存入Redis(或数据库),并设置过期时间(如2小时);
  3. 客户端存储Token:服务器返回Token给客户端,客户端将其存入Cookie或LocalStorage;
  4. 后续请求验证:客户端每次请求时,在Header(如Authorization: Bearer <token>)中携带Token;
  5. 服务器校验:服务器从Redis中查询Token:
    • 若不存在(或已过期):拒绝访问,返回“未登录”;
    • 若存在:从value中获取用户ID,查询数据库确认用户信息,验证通过后返回资源。
传统Token流程图解
客户端 服务器 Redis 数据库 登录阶段 1. 登录请求 (账号密码) 2. 生成Token (存储) 3. 存储Token (确认) 4. 返回Token 后续请求阶段 5. 请求+Token (业务接口调用) 6. 查询Token (验证有效性) 7. 验证存在 (返回用户ID) 8. 查询用户信息 (根据用户ID) 9. 返回资源 (业务数据) 客户端 服务器 Redis 数据库

3. 优缺点:分布式友好,但依赖存储

优点
  • 隐藏敏感数据:Token本身是随机字符串,不携带用户信息,避免明文传输风险;
  • 分布式支持:通过Redis等中心化存储,解决Session共享问题,适用于多服务器集群;
  • 灵活可控:可随时在Redis中删除Token(主动吊销),支持强制登出、账号锁定等场景。
缺点
  • 依赖外部存储:每次请求需查询Redis/数据库,增加IO开销,高并发场景可能成为瓶颈;
  • 性能损耗:存储和查询Token的过程会增加服务器响应时间;
  • 架构复杂度:需维护Redis等存储服务,增加系统部署和运维成本。

二、JWT:自包含的“声明式”认证

1. 什么是JWT?

JWT(JSON Web Token)是一种紧凑、自包含的轻量级令牌格式,通过JSON对象存储用户声明信息(如用户ID、角色、过期时间),并通过数字签名保证信息完整性。服务器无需存储Token,仅通过验证签名即可确认身份。

2. 核心组成:三部分构成的“完整凭证”

JWT由三部分组成,用.分隔,每部分均为Base64编码的字符串:

Header.Payload.Signature  
# 示例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  
(1)Header(头部)

声明Token类型和签名算法,如:

{ "alg": "HS256", "typ": "JWT" }  
# alg:签名算法(如HS256RS256);typ:令牌类型(固定为JWT

经Base64Url编码后形成第一部分。

(2)Payload(载荷)

存储用户声明信息,分三类:

  • 标准声明(可选):如iss(签发者)、exp(过期时间)、sub(用户ID)、iat(签发时间);
  • 公共声明:自定义公开信息(如usernamerole);
  • 私有声明:客户端与服务器约定的敏感信息(需加密)。
    示例:
{ "sub": "123456", "username": "zhangsan", "exp": 1717267200 }  

经Base64Url编码后形成第二部分(注意:Base64编码可逆,请勿存放敏感信息!)。

(3)Signature(签名)

通过Header指定的算法(如HS256),对编码后的Header、Payload和服务器密钥(Secret)进行加密,生成签名:

Signature = HS256( Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload), Secret )  

签名用于验证Token是否被篡改,是JWT安全的核心。

3. 工作原理:“生成-签名-验证”的无状态流程

JWT的认证流程无需外部存储,核心是通过签名确保信息可信:

JWT认证流程详解
  1. 用户登录:前端提交账号密码,服务器验证通过后,生成Header和Payload;
  2. 生成签名:用服务器密钥(Secret)对Header和Payload进行签名,拼接为JWT返回给客户端;
  3. 客户端存储JWT:存入Cookie或LocalStorage;
  4. 后续请求验证:客户端请求时携带JWT,服务器接收后:
    • 分离Header、Payload、Signature;
    • 用相同密钥和算法重新计算签名,对比是否与接收的Signature一致(验证未篡改);
    • 检查Payload中的exp(过期时间)、iss(签发者)等声明(验证有效性);
    • 验证通过后,直接从Payload中提取用户信息(如sub用户ID),无需查询数据库。
客户端 服务器 1. 登录请求(账号密码) 2. 验证身份\n3. 生成Header+Payload并签名生成JWT 4. 返回JWT 5. 后续API请求(携带JWT) 6. 验证JWT签名及声明(如exp, iss) 7. 返回请求资源 客户端 服务器

4. 优缺点:无状态高效,但灵活性受限

优点
  • 无状态:服务器无需存储Token,减轻Redis/数据库压力,支持高并发和水平扩展;
  • 自包含:Payload携带用户信息,减少数据库查询,提升响应速度;
  • 跨语言/跨域:基于JSON和Base64,支持多语言解析,适用于分布式系统和跨域场景。
缺点
  • 无法主动吊销:JWT生成后无法修改,若需强制登出(如账号被盗),需等待Token自然过期(或结合黑名单机制,违背无状态初衷);
  • Payload安全风险:Base64编码可逆,若存放敏感信息(如手机号),需用非对称加密(如RS256);
  • Token体积较大:Payload信息越多,JWT越长,可能增加网络传输开销。

三、传统Token与JWT的核心区别

对比维度传统TokenJWT
本质随机字符串凭证包含声明的自验证令牌
存储依赖依赖Redis/数据库存储无需存储(自包含)
验证方式查询存储系统确认有效性本地验证签名和声明
状态性有状态(需记录Token状态)无状态(Token自带所有信息)
灵活性支持主动吊销、动态过期无法修改,过期不可控
性能依赖IO查询,性能损耗较高本地计算验证,性能更优
适用场景需要频繁吊销、权限动态变化无状态、高并发、跨域认证

四、选型建议:如何选择适合的认证方案?

选传统Token:

  • 主动控制令牌生命周期:如电商平台“踢下线”功能、管理员强制登出;
  • 动态权限管理:用户权限变更需实时生效(传统Token可通过Redis更新value中的权限信息);
  • 敏感操作保护:结合Redis实现Token黑名单(如检测异常登录时临时封禁)。

选JWT:

  • 无状态架构:微服务、分布式系统,避免存储依赖(如K8s集群中的多节点认证);
  • 高并发场景:减少数据库/Redis查询,提升接口响应速度(如秒杀系统、API网关认证);
  • 跨域/跨服务认证:前后端分离、多端应用(Web/APP/小程序)共享认证状态。

传统Token和JWT并非对立关系,而是针对不同场景的技术选择。传统Token通过“存储-校验”保证灵活性,适合需要动态控制的场景;JWT通过“自包含-签名验证”实现无状态高效,适合高并发、分布式架构。

实际开发中,甚至可结合两者优势:用JWT作为传统Token的“载体”,将用户基本信息存入JWT(减少查询),同时在Redis中记录Token状态(支持吊销)。最终,选型的核心是平衡安全性、性能与业务需求——没有最好的方案,只有最适合的方案。

http://www.lqws.cn/news/578251.html

相关文章:

  • VMware 在局域网环境将虚拟机内部ip 端口开放
  • 使用SRS+ffmpeg实现https推流flv
  • python+uniapp基于微信小程序面向品牌会员的在线商城系统
  • 如何让Excel自动帮我们算加减乘除?
  • 基于llama-factory+ollama+vllm加速大模型训推生产
  • 深入 ARM-Linux 的系统调用世界
  • C++ std::list详解:深入理解双向链表容器
  • 分库分表之实战-sharding-JDBC
  • 【数论 拆位法】P10308 「Cfz Round 2」Osmanthus|普及+
  • 车辆工程中的压力传感技术:MEMS与薄膜传感器的实战应用
  • 从设计到开发一个小程序页面
  • Java + 阿里云 Gmsse 实现 SSL 国密通信
  • 用基础模型构建应用(第四章)AI Engineering: Building Applications with Foundation Models学习笔记
  • Springboot + vue + uni-app小程序web端全套家具商场
  • MongoDB 安装使用教程
  • 第81题:搜索旋转排序数组Ⅱ
  • 【软考高项论文】论信息系统项目的干系人管理
  • 百度文库智能PPT月访问量超3400万,用户规模翻倍增长
  • 中钧科技亮相2025 亚欧商品贸易博览会,赋能数字经济新未来!
  • pyspark driver 上传pod本地文件到对象存储
  • AWS 开源 Strands Agents SDK,简化 AI 代理开发流程
  • Hive SQL 实战:电商销售数据分析全流程案例
  • Git远程仓库迁移与分支关联技术分享
  • 【Python使用】嘿马python运维开发全体系教程第2篇:日志管理,Linux概述【附代码文档】
  • 【硬核数学 · LLM篇】3.1 Transformer之心:自注意力机制的线性代数解构《从零构建机器学习、深度学习到LLM的数学认知》
  • Android Compose Modifier 详细解析
  • K8s-Pod深度解析
  • 鸿蒙进阶——Mindspore Lite AI框架源码解读之模型加载详解(五)
  • 阶段二开始-第一章—8天Python从入门到精通【itheima】-121节+122节(函数和方法的类型注解+Union联合类型注解)
  • Ruby 安装使用教程