分布式架构下 OAuth 2.1 自定义认证流:Login 重定向后 Cookie 丢失及 SSO 如何设计?

1. 业务流程描述 (核心逻辑)

我正在设计一套前后端分离的认证流程,省略了用户手动确认授权的步骤,目标是实现自动登录跳转。逻辑如下:

登陆页面与认证授权不在同一个域名下,登陆接口与授权接口在同一个项目中

  1. 前端发现未登录:用户访问业务系统,前端检测无 Token,跳转至后端授权接口 /auth/authorize
  2. 后端判断状态/auth/authorize 从 Cookie 中尝试获取 login_ticket

    • 如果没有 Cookie:后端 302 重定向到前端登录页面 login-page.html
  3. 用户登录:前端提交账号密码到 /auth/login
  4. 设置状态并回调:后端验证成功后,设置 Set-Cookie: login_ticket=...,后端并再次 302 重定向回 /auth/authorize
  5. 下发 Code:此时 /auth/authorize 应该能读到 Cookie,判断已登录,直接下发授权码 code

2. 核心代码片段

2.1. 登录设置 Cookie 并重定向

// /auth/login 逻辑

String ticket = IdUtil.fastSimpleUUID();
redissonHelper.setString("auth:ticket:" + ticket, userId, 300);

// 设置 Cookie
ResponseCookie cookie = ResponseCookie.from("login_ticket", ticket)
    .path("/")
    .httpOnly(true)
    .secure(false) // 本地 HTTP 环境
    .sameSite("Lax")
    .build();
httpServletResponse.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());

// 重定向回授权接口
httpServletResponse.sendRedirect("/auth/authorize?response_type=code&...");

2.2. 授权接口判断 Cookie

// /auth/authorize 逻辑

Cookie cookie = JakartaServletUtil.getCookie(httpServletRequest, "login_ticket");
String userId = (cookie != null) ? redissonHelper.get("auth:ticket:" + cookie.getValue()) : null;

if (StrUtil.isBlank(userId)) {
    // 为登陆跳回登录页
    httpServletResponse.sendRedirect("http://localhost:3000/login-page");
    return;
}
// 下发 code...

3. 核心代码片段

  1. 分布式下的状态保持:虽然我用了 Redis 存储 Ticket,但在前后端分离且跨端口的情况下,302 跳转时 Cookie 的可靠性如何保证?
  2. 安全性疑问:在 OAuth 2.1 规范下,这种“账号登录 -> 设置 Cookie -> 授权接口重定向”的交互模式是否是最佳实践?

4. 期待建议

  1. 在集群环境下,有没有比 Cookie 更稳妥的方式来串联 /login 和 /authorize 这两个接口?
  2. 如果要做单点登录 (SSO),这套逻辑需要如何扩展?
  3. 我这种实现方式是否可行

希望得到技术大佬们的指点!

阅读 793
1 个回答

老老实实在url拼接参数吧,oauth自己协议内部都没有通过header的方式去传递client_id这些参数,那你为何要自己这么搞?你要是登陆后纯在自己系统内部转发/auth/authorize,不走网关,数据还在,走网关或者登录接口和/auth/authorize不在一个服务,不就拉闸了?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进