Rails单体应用使用JWT鉴权重定向到NextJS的安全实现方案咨询
跨域名Rails迁移NextJS场景下JWT鉴权安全方案
以下方案完全满足跨域名部署要求,且全程不需要用户二次登录:
第一步:Rails侧重定向流程处理
- 用户在旧Rails单体应用中处于登录状态,点击跳转NextJS的链接时,Rails后端先生成单次有效、有效期控制在60~120秒的临时授权码,将授权码与当前用户ID绑定后存入Redis或Rails内置缓存,标记为未使用状态
- Rails返回302重定向响应,将授权码作为URL Query参数拼接到NextJS目标页地址后,示例:
https://your-next-domain.com/target/page?auth_code=abc123xyz
注意:禁止直接将长效JWT放在URL中传递,URL会留存到浏览器历史、服务端访问日志中,泄漏风险极高,单次短有效期授权码可以把泄漏后的风险降到最低
第二步:NextJS侧授权码换JWT处理
服务端优先处理(NextJS Middleware/Server Components/服务端渲染逻辑均可实现)
- 访问请求到达NextJS服务端后,首先提取URL中的
auth_code参数,由NextJS服务端直接向Rails后端的专门换票接口发起POST请求,携带auth_code参数 - Rails侧校验逻辑:检查
auth_code是否存在、未过期、未被使用,校验通过后用jwtgem生成对应权限的JWT(可按需设置有效期,建议2小时以内),同时将该auth_code标记为已使用,避免重放攻击,最后返回JWT给NextJS服务端 - NextJS服务端拿到JWT后完成两个操作:
- 给响应设置
HttpOnly、Secure、SameSite=Lax属性的第一方Cookie,存储JWT,该Cookie仅属于NextJS的域名,不需要和Rails同域,完全满足跨域部署要求 - 302重定向到去除
auth_code参数的目标页面,避免授权码留存在浏览器历史记录中
- 给响应设置
第三步:双端调用Rails API的鉴权实现
NextJS服务端调用
直接从请求携带的Cookie中读取JWT,放到API请求的Authorization: Bearer <JWT>请求头中调用Rails接口即可
NextJS客户端调用
优先走代理模式,安全性最高:
- 客户端不直接调用Rails API,而是请求NextJS自身的API路由,由NextJS服务端从Cookie中提取JWT后转发请求到Rails,拿到结果后返回给客户端,全程客户端接触不到JWT,可避免XSS攻击导致的令牌泄漏
如果确实需要客户端直接调用Rails API: - 在服务端渲染页面时,将JWT注入到页面的全局变量中,示例:
window.__USER_JWT__ = "<JWT内容>",同时做好页面的XSS防护,且JWT需要设置更短的有效期,配合无感刷新机制使用
可选优化项
- 可增加JWT刷新机制:NextJS服务端检测到JWT即将过期时,直接用旧JWT向Rails请求换发新JWT,更新Cookie即可,用户全程无感知
- 可增加JWT黑名单机制,用户登出时将当前JWT加入黑名单,避免令牌被盗用后仍可访问
内容的提问来源于stack exchange,提问作者Merlin Mason
相关产品推荐
相关产品推荐

