拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Cookie与JWT深度解析:登录态原理、常见坑与安全实践

不知道你有没有过这种经历后端明明返回了数据前端却拿到一个 401或者同一个接口在浏览器里正常一换到 JMeter 跑脚本就全挂再或者你刚改完一个权限配置发现别人把请求里的身份标识一换就绕过去了。这些问题绕来绕去最后全逃不开两个东西——Cookie 和 JWT。只要做 Web 开发不管你是后端、前端还是搞安全测试的这两个词一定会撞到你脸上。现在的项目要么用 Session Cookie 做登录态要么用 Spring Security JWT 做无状态认证很多老项目干脆两边都有。前阵子我帮客户重构一个旧的留言板系统就是因为 Cookie 的 Domain 配错导致登录态串站后来又因为 JWT 的密钥太弱被爆破出一堆管理员 token。这篇文章我就把 Cookie 和 JWT 的核心原理、实际用法、工具调试手段以及常见的坑一次讲透重点聊聊 JWT 的续签方案、SPA 项目里的验证码流程还有 Burp、JMeter、Reqable 这类工具的实际操作。1. 内容整体设计与思路拆解1.1 为什么 Web 登录态必须有个“凭据”HTTP 从设计上就是个无状态协议。服务器处理完一个请求就忘了你是谁下一次请求又是陌生人。但业务系统不可能接受这种“失忆”——你登录了一次总不能每点一个按钮都再输一次密码。所以必须有一种办法让客户端保存一个东西每次请求带着它过去让服务器一眼确认“这人我认识”。这个“东西”就是身份凭据。Cookie 和 JWT 都是凭据的具体容器只是装的东西和验证方式完全不一样。Cookie 更像“更衣室手牌”你在服务器这边有个储物柜Session手牌上只写个号码真正的东西都放在柜子里。JWT 更像是“盖章通关文牒”一堆写好的承诺用户ID、角色、过期时间盖上了服务器的章谁拿着这份文牒来服务器拆开验一下章真不真就认。这两套模型的区别决定了它们的适用场景。Cookie Session 天然适合传统的服务端渲染项目登录态需要能主动吊销比如管理员踢人下线、数据集中管理很方便。JWT 则适合前后端分离的 SPA、移动端 App、微服务网关鉴权因为服务端不需要存任何会话数据验签通过就放行。没有谁绝对好关键看你的架构偏向哪边。1.2 方案选型如何判断项目该用 Cookie 还是 JWT项目选型的时候我一般会先问三个问题第一你有没有一个集中的存储可以放会话数据如果有 Redis、数据库这种现成的中间件那就别犹豫Cookie Session 或 Spring Session 组合很稳。如果后端是 Serverless 函数、多个无状态微服务实例来回轮询那 JWT 才是最优解因为每个服务都可以独立验签不用每次去 Redis 里查一次。第二你的客户端类型是什么如果是浏览器Cookie 的 HttpOnly 属性可以防 XSS 直接偷走身份信息而且浏览器对 Cookie 的落地和携带都是自动的开发成本极低。如果是 App 或小程序你没有浏览器帮你自动管理 Cookie通常更倾向把 JWT 放在 Authorization header 里自己管理。第三你的业务是否需要对会话的实时可控性比如电商后台要求用户改密码后立刻失效所有 tokenJWT 就显得很尴尬它没法立刻作废除非引入黑名单那又变成有状态了。这种强管控场景Cookie Session 明显更省心。务实一点说很多项目最终都是混合方案——用户登录认证走 Cookie Session接口层面再用 JWT 临时授权给第三方调用。我这次写的留言板系统就是这种思路后面会具体展开。2. Cookie 和 Session 的底层原理与实战2.1 Cookie 的四个关键属性Expires、Domain、Path、HttpOnlyCookie 的本质就是一小段字符串由服务器通过Set-Cookie响应头下发给浏览器浏览器存起来之后每次请求都按规则原样带回去。看起来特别简单但恰恰是那几条“按规则”最容易出事。先说过期时间。Expires是绝对时间点Max-Age是相对秒数。如果两个都设置了Max-Age 优先。会话型 Cookie 不设置过期时间浏览器一关就没了这种适合做临时登录态。带过期时间的 Cookie 会持久化在磁盘上适合做“记住我”。Domain 和 Path 是浏览器判断“要不要带这个 Cookie”的规则。Domain 决定哪些域名接受这个 CookiePath 决定哪些路径前缀会带上。最常见的翻车现场是把 Domain 设置成localhost然后上了生产环境之后发现 Cookie 就是种不进去或者是把 Domain 留空导致子域名之间登录态不互通。HttpOnly 这个属性必须重点说。只要设了HttpOnly浏览器里的 document.cookie 就读取不到这条 CookieXSS 脚本偷不走被窃取的风险直接降一半以上。网上很多老教程写登录后用 JS 去 document.cookie 里拿 session id这完全是错误示范。Session 标识这种核心凭据理应设置 HttpOnly让前端 JS 碰都不碰。Secure 属性表示只在 HTTPS 下发送。生产环境必须加不然中间人可以抓包直接拿 Cookie 冒充登录态。本地开发 http 环境下浏览器会无视带 Secure 的 Set-Cookie这也是新手常遇到的“本地好好的线上登录不上”的原因之一。2.2 从 Session 到 Redis集中式会话是怎么运作的有了 Cookie 这个载体Session 的机制就很清晰了用户带上账号密码请求登录服务器比对密码正确后在服务器内存或 Redis里创建一条记录生成一个随机字符串作为 sessionId然后通过 Set-Cookie 把 sessionId 返回给浏览器。浏览器之后每次请求都带上它服务端拿 sessionId 去存储里查出对应的用户信息完成身份识别。这段流程里最关键的一点数据存在服务器Cookie 里只有一把“钥匙”。所以 Session 模式下你想踢人下线直接把服务端那条 Session 删掉就行想实现在线人数统计去 Redis 数一数 session key 有多少个就完了。集中式会话在很多场景下就是比无状态 token 优雅。多服务器部署时Session 一定要外置到 Redis否则用户在 A 机器登录了下一个请求被负载均衡转到 B 机器B 机器内存里没有这条 session用户就又被踢回去了体验极其糟糕。Spring 生态下用 Spring Session 可以一行注解把默认内存 Session 替换成 Redis 存储。实际操作时还有个细节sessionId 这个 Cookie 建议同时加 HttpOnly 和 SameSite。SameSite 有两个常见取值Strict严格禁止跨站携带安全性最高但体验差通过导航跳转到站点时 Cookie 也不带Lax则在部分场景下允许带比如顶级导航。全球范围内的标准趋势是默认 Lax如果你不需要被第三方网站跳转进来时保持登录态别犹豫直接上 Strict。2.3 Cookie 和 Session 的区别一张表说清很多面试题会问 Cookie 和 Session 的区别但实际工作中这个问题更像是在问“你是用客户端存储还是服务端存储”。我整理一个对照表你直接拿去做参考维度CookieSession存储位置浏览器本地服务器内存/Redis/数据库数据容量单个 Cookie 约 4KB理论无上限安全性容易被 XSS 读取HttpOnly 可防只在服务端客户端拿不到扩展性天生支持分布式需要共享存储Redis才支持分布式主动失效服务器无法直接删除浏览器 Cookie后端删 session 即刻失效适用场景记住偏好、埋点标识、会话 ID 载体登录态、购物车、支付状态核心记忆点就一句话Cookie 管的是“怎么存放和传输”Session 管的是“服务端数据存哪”。两者配合是经典方案但并不是绑定关系——你也可以把 Session ID 放在请求头里传输就不用 Cookie。2.4 实操现场Java 里用 Cookie Session 做登录考虑到现在很多老项目还是 Java 技术栈我把一个最朴素的实现流程写出来。登录接口校验通过后往 Session 里放用户对象同时让容器生成默认的 JSESSIONID Cookie 返回。PostMapping(/login) public String login(RequestBody LoginRequest req, HttpSession session) { User user userService.checkPassword(req.getUsername(), req.getPassword()); if (user null) { throw new RuntimeException(用户名或密码错误); } // 把用户信息放入 Session之后在其它接口中通过 session.getAttribute(user) 获取 session.setAttribute(user, user); return 登录成功; }其它业务接口里不用再查库直接GetMapping(/profile) public User profile(HttpSession session) { User user (User) session.getAttribute(user); if (user null) { throw new RuntimeException(未登录); } return user; }默认情况下容器会创建名为JSESSIONID的 Cookie。Spring Boot 中你可以在配置里改名称、过期时间更重要的是设置 HttpOnlyserver: servlet: session: cookie: http-only: true secure: false same-site: lax我见过不少团队直接在拦截器里检查session.getAttribute(user)是否为空来判断登录态这在单体应用里完全够用。但一旦你开始做前后端分离或者接口要同时给 App 用这套方案就会变得很别扭因为 App 端不会主动维护 JSESSIONID Cookie这时候就该考虑 JWT 了。3. JWT 的核心机制与手写实现3.1 JWT 的三段式结构Header、Payload、SignatureJWT 全称是 JSON Web Token它把身份信息本身直接编码进 token 里而不是只放一个索引。一个完整的 JWT 长这样eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEwMDEsInJvbGUiOiJhZG1pbiIsImV4cCI6MTczMDAwMDAwMH0.8i3Fh4HxgNOYvXBJc-XxgSJFVyKlcCo2ki3jQmFRAoA用.分成三段。第一段是 Header里面声明了签名算法和 token 类型。第二段是 Payload明文存储一些业务声明比如用户ID、角色还有标准字段exp过期时间、iat签发时间等。第三段是 Signature签名这是整个 token 不能被伪造的关键。Header 和 Payload 只是 Base64Url 编码不是加密谁都能解出来看。所谓“防伪造”全靠第三段签名只有当签名的密钥只有服务器知道时别人才不可能造出合法的 token。很多人搞不清这个点以为 JWT 里的内容别人看不到随手把密码塞进去结果一抓包全裸奔。签名计算的过程大致是signature HMACSHA256(base64UrlEncode(header) . base64UrlEncode(payload), secret)服务器收到 token 后用相同的密钥重新计算签名如果和 token 自带的签名一致就证明这份 token 确实是你发的、而且内容没有被篡改过。这就是 JWT 的“验签”逻辑。3.2 HS256 和 RS256两种主流签名算法怎么选JWT 签名算法里 HS256 和 RS256 最常见。HS256 是对称加密加密和解密用同一个 secret实现简单性能好但要求所有验签的服务都必须持有同一个 secret一旦服务数量变多密钥分发和轮换都是麻烦事。RS256 是非对称加密私钥签名、公钥验签签发 token 的服务持有私钥其它验签服务只需要拿到公钥安全性明显更好。选型的时候我的建议很直接如果你的系统只是单一后端服务HS256 配一个高强度 secret 完全够用如果你在做微服务或开放平台多个服务都要验签果断用 RS256这样私钥只存在认证中心其它服务怎么泄露公钥都不会影响 token 的防伪性。还有一类比较危险的是alg: none。这是早期 JWT 规范里允许的调试选项表示不签名。如果后端没有做算法白名单校验攻击者可以把 header 改成{alg:none}然后去掉签名部分直接伪造一个管理员身份的 token 秒进系统。我在安全巡检里见过不止一次这个漏洞处理方式就是在验签代码里先判断算法类型只允许你期望的那几种其它一律拒绝。3.3 签名校验的完整过程服务端是怎么认人的JWT 验签分三步走。第一步拆解 token按.split 成三段缺一不可。第二步重算签名用自己的密钥和 header、payload 重算一遍跟 token 里带的 signature 比对不一样直接 401。第三步校验 payload 里的exp过期时间当前时间大于exp就拒绝放行。很多新手只做第二步、忘了第三步。签名确实是对的但 token 早就过期了还一样能用这就是重大漏洞。更细致一点还要校验iat签发时间不能晚于当前时间太久校验iss签发者是否合法甚至可以校验aud受众是不是自己这个服务——防止一个服务签发的 token 被拿去访问另一个服务。拿 Java 的 jjwt 库举例验签代码就这些行// 解析并校验签名和过期时间 Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody();如果签名错误会抛SignatureException过期了会抛ExpiredJwtException。业务代码里分别捕获并给出对应的响应提示即可。3.4 JWT 续签方案滑动过期和 Refresh Token 机制JWT 无状态特性带来的最大痛点就是“发出去的 token 没法主动作废”因此过期时间通常设置得比较短。但设置得太短用户操作一会儿就要重新登录体验又差。所以才有了续签这个必须解决的话题。方案一叫滑动过期。只要用户还在活跃就给他续。前端在每个请求的响应里检查 token 的剩余有效期比如低于总时长的四分之一就用旧的 token 调一次刷新接口服务器验签通过后重新签发一个新的 token把剩余时间拉满。这种方案对用户体验最友好代码也简单代价是刷新接口实际上承认旧 token 可用严格来说做不到强安全。方案二是 Refresh Token即双 token。Access Token 有效期短比如 15 分钟到半小时给用户直接用到各个接口里。Refresh Token 有效期长几天到一个月专门用来换新的 Access Token。用户 Access Token 过期了前端用 Refresh Token 去换一张新的换完 Refresh Token 本身默认也会轮换旧的直接失效。普通用户根本感知不到 Access Token 过期这件事但服务器随时可以通过吊销 Refresh Token 让对方下次请求时被挡住。我个人的经验是做内部管理系统滑动过期一把梭就够了省心做对外的用户系统特别是涉及支付和订单这类敏感操作的还是老老实实上双 token 方案。记得给 Refresh Token 单独建一张表存 hash方便吊销。3.5 SPA 项目里的 JWT 验证码登录流程SPA单页应用里的登录大多是这样前端把用户名密码还有验证码一起 POST 给后端后端校验证码、校验账号密码都通过后签发 JWT 返回前端把 token 存起来localStorage/sessionStorage 或者内存变量之后所有请求都在 header 里带Authorization: Bearer token。验证码环节有个常见坑后端生成验证码图片时通常会配套一个验证码 ID把验证码答案存在 Redis 里键名就是验证码 ID。前端提交登录请求时要把用户输入的验证码和这个验证码 ID 一起提交后端才能比对。很多人只传验证码不传 ID导致每次比对都拿不到原始答案怎么输都错。另外一个更隐蔽的问题是前端存储 token 的容器。localStorage 虽然方便但任何 XSS 漏洞一触发token 就被拖走了。更稳妥的办法是放在内存变量里用户刷新页面后登录态丢了再想办法用 Refresh Token 拉回来。既保住了体验又减少被偷的风险。JWT 的 CORS 跨域也经常出幺蛾子。跨域时Authorizationheader 是自定义请求头会触发预检请求preflight。后端配置 CORS 时allowedHeaders里必须显式包含Authorization不然浏览器会拦下一大片携带 token 的请求。Spring Boot 里就是用allowedHeaders(*)或者明确列出。4. 工具实战与安全排查4.1 Burp 修改 Cookie抓包后如何手动伪造请求身份Burp Suite 是搞 Web 安全测试的老牌工具。调试 Cookie 或 JWT 最常用的方式就是抓包后直接改请求再放行看响应。流程不复杂浏览器代理挂到 Burp 的 8080 端口登录系统后把一个请求发送到 Repeater 标签页。在 Repeater 里你能看到完整的请求头其中就有整段的 Cookie。把JSESSIONID或 JWT 替换成你想测试的值点击 Go 发送就能看到服务端对这个修改过的身份的响应。我常用的几个安全测试思路把当前用户的 sessionId 改成另一个在线用户的 sessionId如果能猜或拿到测试是否存在会话固定攻击。在 JWT 的 payload 里把 userId 或角色改成 admin重算签名再用测试服务端有没有验证签名。修改 token 的exp为未来永久日期测试服务端有没有校验过期时间。把alg改成none把签名去掉测试算法白名单。Burp 还有个更省事的插件叫 JSON Web Tokens能直接对选中的 JWT 做自动解码、改 payload、爆破弱密钥比自己手工拼时间戳和 Base64 效率高一个量级。测 JWT 签名的弱密钥时直接用这个插件加载一份常见弱密钥字典点运行几秒就出结果。4.2 JMeter 设置 Cookie 和提取动态 TokenJMeter 跑接口压测或自动化脚本时如果目标系统用的是 Cookie 登录态你不做处理脚本里每个请求都是裸奔的全被挡在 401。处理方式是给 Test Plan 添加一个HTTP Cookie 管理器。这个组件会自动保存响应里的 Set-Cookie并在同线程的后续请求中自动带上对应 Cookie。大多数 Cookie 场景到这一步就解决并不需要手动提取。JWT 场景麻烦一些。登录接口返回的是 JSON 里的 token不是 Set-Cookie所以要用后置处理器去提取。一般思路是登录请求下加一个JSON 提取器用 JSONPath 比如$.data.token把 token 存进变量比如命名为auth_token再在后续请求的 HTTP Header 管理器里写Authorization: Bearer ${auth_token}注意变量的作用域JSON 提取器默认是当前线程可用如果你开了多线程并发压测每个线程都会在登录请求里拿到自己的 token互不干扰这是对的。如果你把 token 提取到全局属性里反而所有线程共用同一个 token压测结果就不真实了。4.3 Reqable 手动把响应 Cookie 代入下一个接口Reqable 是近两年比较常用的 API 调试工具界面直观有些人拿它替代 Postman。它的 Cookie 管理分自动和手动两层。如果你在设置里打开自动 Cookie 管理Reqable 会在请求响应返回后自动保存 Set-Cookie下一个请求如果域名和路径匹配会自动携带。这个规则跟浏览器行为一致适合快速调试。但偏偏有些后端接口的 Cookie 路径写得不规范或者你要测跨域等异常场景自动管理失效就得手动处理。方法是把第一个响应里的Set-Cookie: sessionidabc123复制出来在下一个请求的 Headers 标签里手动添加一个Cookie头值填sessionidabc123。需要注意手动添加时最好先把自动 Cookie 管理关闭否则两者都带可能重复。也有一些项目习惯把登录态放在响应体的 JSON 里返回一个set-cookie字段的字符串这时候就得用脚本提取。Reqable 支持在请求前和响应后运行脚本把返回的 token 存进环境变量下个接口引用。具体脚本逻辑和 Postman 的 pm.environment.set 差不多上手成本极低。4.4 JWT 常见漏洞总结和密钥泄露案例JWT 的安全问题网上总结得很多我把实际项目里最常碰到的几种列出来你可以对照自查第一类是弱密钥爆破。HS256 的 secret 太短比如secret、123456攻击者拿到一个正常 token就能用现成工具离线爆破密钥。一旦破出来就能自己给自己发行任意身份的 token。我做过的一个测试项目里管理员密钥就是admin这种层级爆破时间不超过 1 秒。第二类是算法混淆攻击。服务端把alg当作可信输入而不做约束攻击者把 RS256 改成 HS256然后用公钥作为 HMAC 的对称密钥来伪造签名。这类攻击专门打那些既支持非对称又支持对称算法的系统防御手段就是白名单只留一种。第三类是密钥泄露。JWT 密钥如果硬编码在代码里又因为某些原因泄露出去比如前端 bundle、GitHub 仓库、配置文件被打包攻击者直接就能签发任意 token。技术圈里这个问题特别典型——我在排查的 Nacos 认证绕过漏洞里就是因为其默认 JWT 密钥定死攻击者可以用公开的默认密钥自己构造一个身份绕过后端认证。安全修复的核心就是改掉默认密钥并且不让别人有可能猜到或拿到这个密钥。第四类是 payload 里的敏感信息泄露。JWT 只是编码不是加密把手机号、身份证放进 payload等于把信息贴在额头上到处走。如果一定要夹带信息务必先对 Payload 做整体加密这就是所谓的 JWE。这里要特别提醒JWT 的密钥管理和密码一样需要定期轮换。稍微稳妥一点的方案是在配置中心里放密钥版本号token 里带上密钥 ID验签的时候通过 ID 找到对应的密钥轮换时旧密钥还能缓冲一段时间。5. 常见问题与排查技巧实录5.1 登录后接口还是 401几条排查思路这个问题在联调现场出现频率极高一般按下面这个顺序排查。先看请求里有没有把凭据带上。浏览器打开开发者工具的 Network 标签点开请求的 Headers看 Cookie 里有没有 JSESSIONID或者 Authorization 里有没有 Bearer token。很多时候前端封装 axios 时忘了在请求拦截器里加 header导致只有登录请求自己带了 token。再看 token 是不是过期了。去 JWT 官网或调试工具里解出 payload看看 exp 字段是几号。开发环境为了方便把 token 时间拉到一年结果测试时改系统时间把日期调到明年登录就一直失败这种案例我见过不少。接着看路径和域名匹配。浏览器里如果请求地址是api.example.com登录页面是www.example.comCookie 的 Domain 没有设置成.example.com那 Cookie 就带不过去页面跳转后登录态全丢。最后检查跨域配置。前后端分离项目里Access-Control-Allow-Origin 没配好浏览器虽然发出去了请求但响应被拦截前端拿不到数据看起来也是“请求失败”的错觉。5.2 HttpOnly 和 SameSite 的使用禁忌HttpOnly 和 SameSite 都是浏览器安全机制但很多人对它们的理解有偏差。一个非常常见的理解误区是用了 JWT 就不需要 HttpOnly。实际上如果你把 JWT 放进 Cookie 里而非 Authorization headerHttpOnly 依然有效能防止 XSS 直接读走 token。但如果你的业务场景必须让 JS 读取 token比如想自己控制发送时机、用 JS 做续签判断就不要放 HttpOnly Cookie转而去严格杜绝 XSS 注入。SameSite 的坑主要在第三方登录跳转和支付回调上。如果你接入的是微信、支付宝这类外部回调这些请求是跨站的SameSite 设置成 Strict 之后Cookie 不会一起带去回调拿不到会话就可能出现“支付成功但订单状态没更新”的问题。遇到这种情况可以把对应路径的 Cookie 单独设置成 Lax或者改用其它方式传参注明来源。5.3 压测场景下 Session 和 JWT 的并发差异JMeter 压测时Cookie Session 模式下每个新用户都需要经过一次真正的写存储操作。如果你的目标是压“登录”接口就会产生大量 Session 记录可能把 Redis 撑爆。压测前要先确认你是在测并发能力还是在测存储极限。JWT 模式下压测相对轻量因为验签是纯 CPU 计算不依赖存储。但要注意 HS256 和 RS256 在并发高企时的 CPU 消耗差异。RS256 验证比 HS256 慢一个数量级压测结果容易把性能瓶颈定位到验签上。系统如果已有成熟的公钥缓存内部系统场景建议优先用 HS256 降低每个请求的算力开销。还有一个压测常见问题Cookie 管理器只能在同一个线程组内保持会话如果你把登录请求放在线程组 A、业务请求放在线程组 B两边变量不共享业务请求拿不到登录接口返回的 token。跨线程组共享数据要借助 __setProperty 函数写进 JMeter 全局属性但并发场景下需要加同步锁做初始化。5.4 权限提升实战留言板案例的 Cookie 伪造测试全过程还是回到开头那个留言板系统。测试目标是通过构造自己的会话身份拿到管理员权限。操作步骤是这样先用普通用户身份登录在 Burp 里抓到请求包翻到 Cookie 字段发现 session 格式是userId1001; roleuser明显是开发同学图省事把关键身份字段直接明文放进了 Cookie。第一步把 Cookie 改成userId1; roleadmin直接放行系统返回了管理后台的数据。这一步说明服务端没有对 Cookie 里的标识做签名保护用户身份完全可信。第二步是完整的修复方案。我把 Cookie 里的用户信息移除改回常规的 sessionId 模式服务端通过 session 里的用户对象去识别身份前端不再传用户标识。服务端代码改成从 session 取用户。第三步是更进一步的改动把整个后台系统的身份认证从 Cookie 迁移到 JWTtoken 里只放 userId、role、exp 三个字段签名算法用 HS256密钥从配置中心动态读取并且做了密钥版本化可以无感轮换。这套改造做完同类“伪造 Cookie 提权”的攻击路径基本被堵死。Cookie 只负责保存会话标识而判断逻辑全部回到服务端或者验签环节。结束语与个人体会做 Web 开发和测试这几年我最大的体会是Cookie 和 JWT 不是一道二选一的单选题它们是同一套身份认证体系里的两种工具。Cookie 管“浏览器怎么保存和发送数据”JWT 管“服务端如何签发和验证数据”实际项目往往是混合使用。如果你还在为项目选型纠结我给一个朴素建议单体后台管理系统Cookie Session 配合 Redis简单稳定好排查前后端分离、需要多端支持、接口要给别人调的直接上 JWT至于敏感系统无论 JWT 多方便都要配刷新令牌、密钥轮换以及黑名单机制兜底。最后再分享一个小技巧——不管是 Cookie 还是 JWT调试环境不要依赖肉眼去看 BASE64 里那串字符。装上对应的浏览器插件或 Burp 扩展把 token 一键解出来看 payload 和过期时间能省下大把排查时间。安全上线前务必用工具跑一遍弱密钥字典这类问题出现一次就足以让整个系统裸奔。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门