面试官嘲笑我把Token放Redis里,该如何应对?
最近,小编看到这样一个问题:
问题地址:
回答
整理了几个不错的回答,分享一下。
MicroOps的回答
你就问他代码上线前有没有做review,有没有做灰度发布、蓝绿发布,每次上线有没有做回归测试,有没有定期做渗透测试、漏洞扫描,安全漏洞有没有做定期修复,生产环境有没有做网络隔离(划分DMZ、内网),有没有准入控制,程序配置文件中密码字段有没有加密,敏感数据落盘(包含日志、数据库)有没有做脱敏和加密。
如果他们公司有一条没做到,就怼他: 垃圾公司。
如果他们公司都做到了,那你的确无话可说。
现在主流的Token方案主要是两种。
第一种是传统的cookie/session方案,工作原理就是服务器生成一个随机会话ID, 并下发给客户端,此方案简单,但是对于分布式、多副本需要用例如redis、mysql之类的服务进行数据共享。直接存token不是什么大问题,但是如果遇到数据库数据泄露可能会导致攻击者通过token登陆到后台,解决方案有很多,比较简单的做法就是存token的hash值,这样可以避免因数据泄露导致的身份伪造。
第二种就是jwt方案,此方案最大优势就是无状态,不用保存会话信息就可以实现分布式、多副本。但缺点是没有会话列表以及吊销会话困难。如果有人token被泄露了,要么等token过期,要么修改jwt密钥让所有会话失效。想要解决此问题,通常就需要引入redis、mysql之类的服务存储token信息,可以将所有已登录的token信息存入数据库,吊销时删除相关token信息,也可以建立token黑名单,将吊销的token信息存入此黑名单。但是直接存入完整token也可能存在方案一类似的风险,解决方案存hash或者是在payload中插入一个tokenid字段,数据库只记录id字段,这样就可以避免因数据泄露导致的身份伪造。
对于token直接入库我没有任何否认的意思,每个公司/项目所需要的安全程度不一样,你们项目如果能接受这个风险,完全可以直接入库。我提到的存token的hash或jwt的tokenid,只是基于存在的风险点,提供了一点建议。存token还是存hash,无非就是一行代码的事情。
如果你秉着技术探讨的态度说token入库完全没有风险,那我可以给你探讨探讨,否则,可以忽略我的论点:
按照问题中所说的token放redis,从安全角度来说:
1、我们不能保证所有维护的人都能有这个觉悟,保证redis只能内网访问,并且都有强口令保护,恰好我们公司另一个团队,以前就出过这样一个事情:redis直接允许公网访问,密码还是弱口令,结果服务器遭挖矿,数据倒是没有泄露。这样的事情我在很多技术群(QQ群)里,看到类似的案例。
2、我们不能保证redis所在的内网,都拥有固若金汤的防火墙规则。恰好我们公司另一个团队又出过类似的事情,为了方便调试把服务器的docker远程控制端口开放到公网,还不需要任何认证就可以使用,结果也惨遭挖矿。如果黑客当时通过横向渗透,我相信可以拿下其他一些服务器的权限,因为很多公司(包括我们公司),内网之间的防护做的并不是特别安全,拿下redis服务器权限也不是不可能。
3、你没法保证你们开放到公网的所有服务都绝对安全,例如以前的fastjson漏洞,或者你的程序存在SQL注入漏洞、任意命令执行漏洞等。
或许你认为你不会存在这些问题,但你不能保证你没有猪队友。 你或许会认为出现问题再修复,只要不是你的token自身的问题就不归你管。那我只能说,想法没错,继续保持。
题外话:
有些人可能认为都脱库了,黑客还需要后台权限吗?
1. 如果我敏感数据加密了,脱库没拿到敏感数据,那么黑客拿到的数据意义不大。但是后台可以查看敏感数据的。
2. 如果黑客想横向攻击,那么可能只脱库不够,还要拿shell权限,才能进一步实施内网渗透。
程序员小富的回答
大概率不是你菜,而是面试官读书读傻了,或者他只背过八股文,没做过复杂的业务。
面试被嘲笑,心态上要稳住。
嘲笑别人技术选型的面试官,通常技术视野都很窄。
人家毕竟是面试官,你不能跟他硬刚我就要存,也不能唯唯诺诺承认我错了。
分析下他是啥心态
他为什么嘲笑你?
面试官的脑回路大概是这样的:
“Token(尤其是 JWT)设计的初衷就是无状态(Stateless)。哎,服务器只要解密签名就知道你是谁,不需要查库。你把它塞进 Redis,不就又变成 Session 模式了吗?那你还用 Token 干嘛?这不是脱裤子放屁吗?”
教科书上确实是这么写的。
但教科书不会告诉你:如果用户手机丢了,想把这个账号强制下线,纯无状态的 JWT 怎么做?
答案是:做不到。
除非你换密钥,让所有用户一起掉线。
为什么要存 Redis?
告诉面试官,把 Token 存 Redis(或者只存 Token 的 ID),不是为了认证,而是为了管理。
我给你总结一下回答的话术,这样是不是合理一点
1. 并没有绝对的无状态,只有可控的状态
话术:
“面试官您说得对,JWT 本身确实是无状态的。但在我们的业务场景里,安全管控的需求高于无状态的需求。我们需要实现一键踢人、多端登录限制(只允许一个手机在线)、修改密码后强制旧 Token 失效等功能。如果不存 Redis 做白名单或黑名单机制,纯无状态的 JWT 无法满足这些业务刚需。”
2. 续签的体验问题
话术:
“如果纯靠 JWT 的 exp 字段,用户用着用着突然过期了,体验很差。我们需要实现滑动过期(用户一直在用,Token 就一直不过期)。把 Token 存 Redis 并设置 TTL,用户每次请求时刷新 TTL,是实现滑动过期成本最低的方案。否则就得引入复杂的 Refresh Token+ Access Token 双令牌机制,对于我们当时的团队规模和并发量来说,Redis 方案性价比最高。”
3. 性能权衡
话术:
“确实,查 Redis 有网络开销。但 JWT 的非对称加密验证(如 RSA)是非常消耗 CPU 的。在并发并没有达到数万 QPS 的情况下,Redis 的毫秒级读取对性能的影响微乎其微,但它带来的业务灵活性(随时封禁、统计在线人数)是纯 CPU 计算换不来的。”
如果他还在杠
如果面试官说:“那你可以用 Refresh Token 存 Redis,Access Token 不存啊?”
这时候你要承认这是更优解,但要强调演进过程。
话术:
“您说的双 Token 方案确实是标准的 OAuth2做法,适合更大规模的系统。
但我们当时考虑到:
1、前后端交互的复杂度(前端要写拦截器处理 401 自动刷新)。
2、Redis 集群极其稳定,并不是瓶颈。所以我们选择了以空间换复杂度的 Reference Token 模式(或者 Token 强校验模式)。架构没有最好的,只有最适合当下的。在那个阶段,这个方案帮我们快速实现了业务且没出过事故。”
真实感悟
如果面试官听完这些还在嘲笑你,甚至还在纠结“Redis 挂了怎么办”(Redis 挂了你整个系统早就挂了,还在乎个登录?),那说明这家公司不去也罢。
真正的技术大佬,都是非常的尊重人的,他甚至会引导你说出答案,不会嘲笑某一种方案咋滴咋滴,他们其实更关心讨论这种方案背后的权衡过程。
Token 存 Redis 可是无数中大型互联网公司的标准做法(Session 共享),有TM什么好丢人的。
亮剑ch的回答
我最近接到个项目,其中有个需求就是后台如果30分钟内没有任何操作,token就失效要重新登录,我想到办法就是用redis存储token的上次操作时间并设置redis的过期时间(与token的过期时间保持一致),有操作时更新redis保存的时间,如果发现上次时间已经过了30分钟就返回失效,除了用redis这个方法我想不到其他办法。
竹露晨曦的回答
Token放在redis是一种方案,JWT也是一种方案。所有的方案都是为了需求服务,脱离需求说方案都是瞎扯淡。
如果面试的人觉得JWT好,你就问他如果JWT发出去后,如果发生了安全问题,怎么从服务端主动失效。
Redis优点是服务端强安全管控,缺点是高并发时需要更多资源;JWT优点是无状态、对于需要跨域认证和高性能的场景友好,缺点是安全性较差,需要被动等待失效。
当然有时候会把二者结合起来用,这一切都取决于具体的需求场景。用Redis没错,用JWT也没错,你要认为JWT比Redis高雅,那就错了。
花宝宝的回答
Token 放 Redis 被嘲笑,通常是面试官觉得这么做不懂 JWT。JWT 的卖点就是无状态——服务端不用存任何东西,token 里自带用户信息和签名,拿到之后验证签名就行,不需要查数据库也不需要查 Redis。
听起来很完美,然后上线了。
产品经理跑过来说:有个用户密码被盗了,要立刻把他踢下线。
纯 JWT 方案,token 签发的时候设了 2 小时过期。被盗的 token 还有 1 小时 45 分钟才过期。这 1 小时 45 分钟里,拿着这个 token 的人可以用被盗账号做任何事。
已经签发的 JWT 没有任何办法立刻失效。“无状态”意味着服务端不记得自己发过哪些 token,自然也没法说“这个 token 作废了”。
上线第一天就撞上这个问题的团队不在少数。
主动踢人下线做不到。
不只是密码被盗。后台管理员要封禁一个违规用户、用户自己修改了密码想让其他设备全部下线、用户点了“退出登录”——这些场景都需要让一个已签发的 token 立刻失效。
纯 JWT 做不到。
为了解决这个问题,只能加一层存储——维护一个“黑名单”。用户被踢下线的时候把 token 加到黑名单里,每次请求来了先查黑名单。
黑名单存哪?内存不行,重启就丢了,而且多个服务实例之间不共享。数据库太慢,每个请求都查一次数据库受不了。
存 Redis。
public void logout(String token) { long expiration = jwtUtil.getExpiration(token); long ttl = expiration - System.currentTimeMillis(); if (ttl > 0) { redisTemplate.opsForValue().set("blacklist:" + token, "1", ttl, TimeUnit.MILLISECONDS); }}public boolean isTokenValid(String token) { if (redisTemplate.hasKey("blacklist:" + token)) { return false; } return jwtUtil.verify(token);}
到这一步,“无状态 JWT”已经不是无状态了。每个请求都要查一次 Redis。
token 续期也是个问题。
用户正在页面上填一个很长的表单,填了 25 分钟,点提交。token 过期了,请求被拒绝,表单内容全丢了。
常见的做法是双 token:AccessToken 有效期短(比如 30 分钟),RefreshToken 有效期长(比如 7 天)。AccessToken 过期了,前端用 RefreshToken 去换一个新的 AccessToken。
RefreshToken 存哪?存 Cookie 可以,但 RefreshToken 要不要支持主动吊销?要的话——又回到 Redis。
另一种是“滑动过期”。用户每次请求都刷新 token 的过期时间。但 JWT 的过期时间写在 payload 里,改了过期时间整个 token 就变了,等于每次请求都签发一个新 token。而且旧 token 在过期之前仍然有效——没法让它失效,除非……加黑名单,存 Redis。
怎么绕都绕不开 Redis。
纯 JWT 真正适合的场景
JWT 的“无状态”在什么时候是真正的优势?跨服务调用。
微服务架构里,用户请求经过网关之后要调用户服务、订单服务、支付服务。如果用传统 Session,每个服务都要去 Redis 查一次 Session 信息。如果用 JWT,网关验证完签名之后把用户信息往下传就行了,下游服务不需要再查任何存储。
用户请求 → 网关(验证 JWT 签名)→ 订单服务(直接从 JWT 解析 userId)→ 支付服务(直接从 JWT 解析 userId)
这种场景下 JWT 的无状态确实省了很多事。但注意,这里 JWT 承担的角色是服务间传递用户身份,不是做登录会话管理。网关那一层照样可以用 Redis 管理用户的登录状态,只是下游服务不需要再查了。
另一个适合 JWT 的场景是一次性的凭证——邮箱验证链接、密码重置链接、临时分享链接。签发一次,用一次,不需要续期也不需要主动吊销。这才是 JWT 自包含特性最舒服的地方。
Token 放 Redis 有什么问题
回到被嘲笑的点,Token 放 Redis 的”问题”是什么?
性能? Redis 单次查询不到 1ms,单机 QPS 十几万。服务能扛一万并发的时候,Redis 那层完全不是瓶颈。
单点故障? Redis Sentinel 或 Redis Cluster 做高可用,主节点挂了自动切换。Session 存 Redis 是业界跑了十几年的成熟方案,从来没有人说“Session 不能放 Redis 因为会单点故障”。
违背了 JWT 的设计理念? 这倒是真的。生成一个 JWT 然后把它整个存进 Redis,每次验证都去 Redis 查而不是验签名——那确实只是用了 JWT 的格式,没用它的能力。这种情况下不如直接生成一个随机字符串当 Session ID,还省了 JWT 编解码的开销。
面试官嘲笑的可能就是这个:用了 JWT 但完全没利用无状态特性,那为什么要用 JWT?这个问题确实值得想清楚。
但 Token 该不该放 Redis,取决于业务需求:
系统需要主动踢人下线、修改密码后其他设备失效、管理员封禁用户 —— 必须有一个中心化的状态存储。Redis 是最合适的选择。至于 token 的格式是 JWT 还是随机字符串,反而是次要的。
系统不需要这些,纯粹是用户登录一次、token 过期了重新登录 —— 纯 JWT 没问题,省一层 Redis 依赖。
大部分业务系统都需要前者。用户管理后台总得有个“强制下线”的按钮吧?
面试怎么答
面试官问 Token 怎么管理,别上来就说“我放 Redis 里",也别上来就说“我用 JWT 无状态”
先说业务需求:系统需不需要主动吊销 token?需不需要踢人下线?需不需要限制同时在线设备数?
需要 → Redis 存 token(或 JWT+ Redis 黑名单),讲清楚为什么纯 JWT 做不了主动吊销。
不需要 →纯 JWT,讲清楚签名验证的流程、过期策略、密钥管理。
面试官想听的不是你选了哪个方案,是你知不知道每个方案的边界在哪。"Token 放 Redis"不丢人,丢人的是说不出来为什么要放。









评论