小程序开发中的JWT认证:用户身份Token生成与验证流程 分类:公司动态 发布时间:2026-04-30

小程序天然采用前后端分离的架构模式,前端与后端API通过HTTP协议交互,而HTTP本身是无状态协议,无法识别请求的用户身份,因此身份认证体系是小程序开发的核心基础环节。本文将基于RFC7519标准,结合小程序的业务特性,完整拆解JWT认证的核心原理、端到端生成与验证全流程、安全最佳实践及常见问题解决方案,为小程序开发者提供可落地的专业认证体系搭建指南。
 
一、JWT核心基础与小程序适配性
 
1. JWT的定义与标准规范
JWT全称JSON Web Token,是RFC7519标准定义的一种轻量级、自包含的令牌格式,用于在网络环境中安全地传输JSON格式的身份信息。其核心特性是自包含与防篡改:令牌本身已包含用户的身份信息与权限声明,服务端无需额外存储状态,同时通过数字签名保证令牌内容无法被非法篡改。
 
2. JWT的核心结构
标准JWT由三部分组成,通过 . 分隔,完整格式为 Header.Payload.Signature ,每一部分均采用Base64URL编码(适配URL传输,移除了普通Base64中的 +  /  = 特殊字符)。
 
(1)Header(头部)
Header用于声明JWT的类型与签名算法,固定包含两个字段:
1) typ :令牌类型,固定为 JWT 
2) alg :签名算法,常用分为两类:
a. 对称加密算法:HS256(HMAC-SHA256),使用同一个密钥完成签名与验证,实现简单但密钥泄露风险高
b. 非对称加密算法:RS256(RSA-SHA256)、ES256,使用私钥签名、公钥验证,私钥仅后端持有,安全性更高,是小程序生产环境的首选
 
示例Header:
 
{
  "typ": "JWT",
  "alg": "RS256"
}
 
(2)Payload(载荷)
Payload是JWT的核心数据载体,用于存放用户身份声明与业务字段,分为三类声明:
1)注册声明(标准字段):RFC7519预定义的标准字段,建议按需包含,核心字段如下:
 
字段 全称 说明
iss Issuer 签发者,小程序场景建议填写小程序 appid,防止跨系统令牌冒用
exp Expiration Time 过期时间,Unix 时间戳,必须大于签发时间
iat Issued At 签发时间,Unix 时间戳,用于计算令牌有效期
jti JWT ID 令牌唯一标识,用于实现黑名单机制,解决令牌主动失效问题
sub Subject 令牌主题,通常固定为user_auth
nbf Not Before 生效时间,在此时间之前令牌无效
 
2)公共声明:可自定义扩展的通用字段,如用户角色、业务场景标识
3)私有声明:业务方自定义的用户身份字段,如用户唯一ID uid 
 
核心注意事项:Payload仅做Base64URL编码,并非加密,任何人拿到令牌都可解码查看内容,因此绝对禁止存放用户手机号、身份证号、小程序session_key、appsecret等敏感信息。
 
小程序场景推荐Payload示例:
 
{
  "iss": "wx1234567890abcdef",
  "exp": 1714468980,
  "iat": 1714461780,
  "jti": "a1b2c3d4e5f6g7h8i9j0",
  "sub": "user_auth",
  "uid": 100001,
  "role": "member"
}
 
(3)Signature(签名)
Signature是JWT防篡改的核心,生成规则为:
1)将Base64URL编码后的Header与Payload用 . 拼接,得到待签名字符串
2)使用Header中指定的签名算法,配合后端密钥/私钥对字符串进行签名
3)对签名结果进行Base64URL编码,得到最终的Signature
 
只有持有正确密钥/私钥的后端才能生成合法签名,任何对Header或Payload的修改,都会导致签名验证失败,从根本上杜绝令牌被篡改的风险。
 
3. 小程序开发选择JWT的核心优势
(1)完美适配小程序环境:无需依赖Cookie,可统一放在HTTP请求头的 Authorization 字段中传输,彻底解决不同小程序平台对Cookie的兼容性问题,请求完全可控。
(2)无状态特性适配分布式架构:令牌本身携带身份信息,后端无需在服务端存储Session状态,无需做Session共享,天然适配微服务、多实例部署的水平扩展需求,降低服务端存储压力。
(3)多端统一适配:一套JWT认证体系可同时兼容小程序、H5、App等多端业务,无需为不同端单独开发认证逻辑,降低研发成本。
(4)安全性可精细化管控:可自定义令牌有效期、签名算法、加密规则,配合小程序HTTPS强制要求、安全域名限制,可构建多层安全防护体系。
 
二、小程序JWT认证端到端全流程
 
小程序JWT认证体系并非独立存在,必须与小程序平台的官方登录流程深度结合,核心分为令牌生成、令牌验证、令牌刷新、令牌失效四大核心阶段,完整端到端流程如下。
 
1. 前置准备工作
在开发认证体系前,需完成三项核心准备:
(1)后端JWT基础配置:确定签名算法(生产环境优先RS256)、公私钥/密钥管理方案、令牌有效期策略、Payload字段规范、统一拦截器逻辑
(2)小程序端基础配置:在小程序后台配置业务域名、request合法域名,确保所有API请求均走HTTPS协议;封装统一的request请求拦截器与storage存储工具
(3)安全基础保障:后端服务全站强制HTTPS,禁用HTTP协议;配置服务器请求头大小限制,避免令牌过长导致请求被拦截
 
2. 阶段一:用户身份初始化与JWT令牌生成
该阶段是认证体系的核心,将小程序平台的用户身份与后端JWT体系绑定,完整步骤如下:
 
步骤1:小程序端获取临时登录凭证
用户打开小程序后,前端调用小程序宿主平台的登录API,获取临时登录凭证code。以微信小程序为例,调用 wx.login() 接口,获取有效期5分钟的临时code,该code仅可使用一次,是换取用户唯一标识的核心凭证。
 
示例代码:
 
wx.login({
  success: (res) => {
    if (res.code) {
      // 拿到code,向后端发起登录请求
      userLogin(res.code);
    }
  }
});
 
步骤2:小程序端向后端发起登录请求
前端将获取到的code,通过POST请求发送至后端登录接口(如 /api/auth/miniprogram-login ),请求体中可附带小程序appid(多小程序场景)、场景值等辅助信息。核心注意:该阶段绝对不能携带任何用户敏感信息,仅传输临时code。
 
步骤3:后端校验code,获取用户唯一标识
后端收到code后,结合小程序的appid、appsecret,调用小程序平台的官方接口(微信为 auth.code2Session ),换取用户的核心身份信息:
(1) openid :用户在当前小程序的唯一标识
(2) unionid :用户在同一主体下多个小程序/公众号的唯一标识,多端打通场景必备
(3) session_key :小程序平台颁发的会话密钥,用于解密用户手机号、授权头像昵称等敏感信息,绝对不能返回给前端,也不能放入JWT的Payload中,需后端加密存储。
 
步骤4:后端用户体系处理
后端根据获取到的openid/unionid查询用户表:
(1)新用户:自动完成注册,生成用户唯一uid,写入用户基础信息
(2)老用户:更新用户最后登录时间、登录设备等信息,确认用户账号状态正常(未封禁、未注销)
 
步骤5:后端生成双Token体系
为平衡安全性与用户体验,小程序场景必须采用双Token机制,避免单Token过期导致用户频繁登录:
(1)Access Token(访问令牌):标准JWT格式,有效期1-2小时,用于所有业务接口的身份鉴权,Payload仅包含核心身份字段,严格控制体积
(2)Refresh Token(刷新令牌):可采用JWT格式或高强度随机字符串,有效期7-30天,仅可用于刷新Access Token,不能用于普通业务接口鉴权,需与用户uid绑定存储
 
生成JWT Access Token的核心流程:
1)按照预定义规范,生成Header与Payload内容,填充iss、exp、iat、jti、uid等核心字段
2)使用RS256算法与后端私钥,对Header+Payload的拼接字符串进行签名
3)对Header、Payload、Signature分别进行Base64URL编码,用 . 拼接成完整的JWT令牌
 
步骤6:后端返回令牌给小程序端
登录接口成功响应,返回Access Token、Refresh Token、Access Token过期时间 expires_in ,禁止返回appsecret、session_key、用户敏感信息。
 
步骤7:小程序端安全存储令牌
前端收到令牌后,对令牌进行对称加密处理,持久化存储在小程序的安全存储API中(微信为 wx.setStorageSync ),禁止存储在全局变量中(小程序冷启动后全局变量会清空),禁止明文存储,防止设备root/越狱后令牌泄露。
 
示例存储代码:
 
// 加密存储令牌
wx.setStorageSync('access_token', encryptToken(res.data.access_token));
wx.setStorageSync('refresh_token', encryptToken(res.data.refresh_token));
wx.setStorageSync('token_expires', res.data.expires_in + Date.now());
 
3. 阶段二:业务请求的令牌携带与验证流程
该阶段是日常业务请求的核心鉴权流程,全链路无感知,分为前端请求处理与后端校验两大环节。
 
(1)前端环节:统一请求拦截器封装
小程序端封装统一的request请求拦截器,所有业务请求发起前,自动完成令牌携带与前置校验:
1)从本地storage中解密获取Access Token,若令牌不存在,直接跳转至登录页
2)将令牌按照标准Bearer认证规范,添加至HTTP请求头中: Authorization: Bearer <access_token> 
3)发起请求,接收响应后统一处理异常状态码
 
(2)后端环节:统一令牌校验拦截器
后端对所有需要鉴权的业务接口,配置统一的拦截器/中间件,按照以下优先级完成令牌校验,任何一步校验失败,直接终止请求并返回对应异常:
1)令牌格式校验:从请求头的 Authorization 字段中提取令牌,校验是否符合 Bearer <token> 格式,是否为三段式JWT结构,无非法字符,无令牌直接返回401 Unauthorized
2)签名合法性校验:使用RS256公钥/HS256密钥验证令牌签名,确认令牌未被篡改,签名不匹配直接返回401
3)标准声明校验:校验令牌的iss是否为当前系统合法签发者、exp是否过期、nbf是否已生效,过期令牌直接返回401,并提示令牌过期
4)黑名单校验:校验令牌的jti是否在Redis黑名单中,若存在(用户登出、账号封禁、密码修改),直接返回401
5)业务身份校验:从Payload中提取uid,查询用户表,确认用户账号状态正常(未封禁、未注销),用户角色与接口权限匹配,权限不足返回403 Forbidden
6)上下文注入:校验全部通过后,将用户uid、角色等身份信息注入请求上下文,供后续业务接口使用,执行业务逻辑并返回数据
 
4. 阶段三:令牌无感刷新机制
当Access Token过期时,前端通过Refresh Token完成无感刷新,无需用户重新授权登录,核心流程如下:
(1)前端收到后端返回的401 Token过期响应,先判断本地是否存在Refresh Token,不存在直接跳转登录页
(2)前端调用后端刷新接口 /api/auth/refresh-token ,仅携带Refresh Token,该接口需做单独的限流防护,防止暴力破解
(3)后端校验Refresh Token的合法性、有效期,确认对应用户账号状态正常
(4)校验通过后,生成新的Access Token,可选滚动更新Refresh Token(旧Refresh Token加入黑名单),返回给前端
(5)前端更新本地存储的令牌,自动重新发起之前失败的业务请求,用户全程无感知
(6)若Refresh Token校验失败,后端返回401,前端清空本地所有令牌,跳转至登录页,强制用户重新授权登录
 
5. 阶段四:用户登出与令牌主动失效
JWT的无状态特性导致令牌签发后,在过期前无法主动失效,因此必须通过黑名单机制解决该问题,登出流程如下:
(1)前端发起登出请求,携带当前Access Token,同时清空本地存储的所有令牌,跳转至登录页
(2)后端解析令牌的jti与exp过期时间,将jti存入Redis黑名单,设置黑名单key的过期时间与令牌exp一致,过期后自动删除,节省存储空间
(3)针对用户密码修改、账号封禁、权限变更等场景,需将该用户名下所有未过期的令牌jti批量加入黑名单,强制用户重新登录,彻底解决权限变更后的令牌残留风险
 
三、小程序JWT认证安全最佳实践
 
1. 签名算法与密钥管理规范
(1)生产环境强制使用非对称加密算法RS256/ES256,禁止使用HS256对称算法,避免密钥泄露导致全量令牌被伪造
(2)私钥/密钥绝对禁止硬编码在代码中,需存储在环境变量、加密配置中心,定期轮换,小程序端绝对不能存储任何签名相关密钥
(3)公钥仅用于令牌验证,可公开分发,但需防止被恶意替换,建议通过配置中心统一管理
 
2. 令牌生命周期管控
(1)严格控制Access Token有效期,建议1-2小时,金融、支付等高安全场景不超过30分钟,绝对禁止设置永久有效令牌
(2)Refresh Token有效期建议7-30天,根据业务安全等级调整,高安全场景可缩短至3天,刷新时采用滚动更新机制,降低泄露风险
(3)Payload中必须包含iat签发时间与jti唯一标识,为黑名单机制提供基础
 
3. 传输与存储安全
(1)全程强制HTTPS协议,禁止HTTP传输令牌,小程序后台严格限制request合法域名,防止恶意域名请求
(2)令牌必须放在HTTP请求头的Authorization字段中传输,禁止拼接在URL中,防止日志、Referer泄露
(3)小程序端必须加密后持久化存储令牌,禁止明文存储,禁止存储在全局变量或页面缓存中
(4)配置服务器请求头大小限制,Nginx默认 client_header_buffer_size 为4k,避免Payload过大导致令牌超长被拦截
 
4. 防护体系增强
(1)必须实现基于jti的Redis黑名单机制,覆盖登出、改密、封禁、权限变更全场景
(2)拦截器必须校验用户账号状态,不能仅验证签名,避免封禁用户通过未过期令牌访问系统
(3)防御XSS攻击:小程序端对用户输入内容做转义处理,防止恶意脚本注入获取本地存储的令牌
(4)防御重放攻击:对核心接口添加请求时间戳校验、nonce随机数校验,防止令牌被截获后重复使用
(5)接口限流:对登录、刷新令牌接口做严格的限流与IP风控,防止暴力破解与恶意请求
(6)权限最小化:Payload中仅存放必要的身份信息,接口鉴权时严格校验用户权限,防止越权访问
 
四、常见问题与解决方案
 
常见问题 根因分析 解决方案
Token 过长,请求被服务器 / CDN 拦截 Payload 中存放了过多用户信息,导致令牌体积超过请求头限制 Payload 仅保留 uid、jti、exp 等核心字段,其他用户信息通过接口查询,禁止存放冗余数据
用户登出后,令牌依然可正常使用 未实现黑名单机制,JWT 无状态特性导致服务端无法主动失效令牌 基于 Redis+jti 实现黑名单,登出、改密、封禁时将令牌加入黑名单,拦截器强制校验
Token 过期导致用户频繁重新登录 单 Token 机制,有效期与用户体验无法平衡 实现双 Token 无感刷新机制,短有效期 Access Token + 长有效期 Refresh Token
密钥泄露后,攻击者可伪造任意令牌 使用 HS256 对称加密算法,单密钥同时用于签名与验证 替换为 RS256 非对称加密算法,私钥严格保密,仅后端持有,公钥用于验证
令牌被解码后,敏感信息泄露 误以为 Base64URL 是加密,在 Payload 中存放了手机号、session_key 等敏感数据 Payload 绝对禁止存放敏感信息,敏感数据需通过 JWE 加密传输,或单独通过 HTTPS 接口获取
用户账号封禁后,仍可通过令牌访问系统 仅校验令牌签名与有效期,未校验用户账号状态 拦截器中增加用户状态校验步骤,确认用户账号正常后才可执行业务逻辑
 
在实际小程序开发中,开发者需牢牢把握「签名防篡改、数据非敏感、传输全加密、状态可管控」四大核心原则,结合小程序平台的官方登录流程,搭建双Token认证体系,落实本文提到的安全最佳实践,才能在保障用户体验的同时,构建起高安全、高可用、可扩展的小程序身份认证体系,为业务稳定运行提供核心支撑。
在线咨询
服务项目
获取报价
意见反馈
返回顶部