OAuth 2.0 + JWT 单点登录

OAuth 2.0 + JWT 单点登录实战 一、从一个登录按钮说起 你在商家后台(merchant.shop.com)点了"登录",页面跳转到了一个统一的登录页,你输入账号密码,然后又跳回了商家后台——你已经在系统里了。然后你打开运营后台(ops.shop.com),不用再输密码,直接进去了。 这就是单点登录(SSO)。背后有三个角色在协作: sequenceDiagram participant Browser as 浏览器 participant Biz as 业务系统\nmerchant.shop.com participant SSO as 认证中心\nsso.company.com Browser->>Biz: 1. 访问商家后台 Biz-->>Browser: 2. 302: 去认证中心登录 Browser->>SSO: 3. 跳转到登录页 SSO-->>Browser: 4. 返回登录页面 Browser->>SSO: 5. 提交用户名密码 SSO-->>Browser: 6. 302: 登录成功,回业务系统 Browser->>Biz: 7. 带着凭证回商家后台 Biz->>SSO: 8. 后端验证凭证 SSO-->>Biz: 9. 返回用户身份 Biz-->>Browser: 10. 登录成功,进入系统 这里面有两个关键问题: 第 5 步中,用户的密码交给了谁? 答案:只交给了认证中心。业务系统从头到尾都没见过用户的密码。 第 7 步中,浏览器带回的"凭证"是什么? 答案:是一个一次性的授权码(code),不是用户名密码,也不是最终的身份令牌。 这就是 OAuth 2.0 授权码模式的核心思路:用户密码只给认证中心,业务系统通过一个间接的"授权码"来确认用户身份。 二、逐帧拆解:一次登录的完整交互 下面以一个真实场景走一遍完整流程。三个参与者: 参与者 对应系统 职责 浏览器 用户正在用的 Chrome / Edge 用户操作的入口,负责跳转和提交凭据 业务系统 CRM 应用(crm.company.com:8080) 用户真正想用的系统,需要确认"你是谁" 认证中心 SSO 服务器(sso.company.com:9000) 唯一能验证用户名密码的地方,签发身份令牌 下面是完整的交互流程——请重点关注每个角色在每一步做了什么: ...

九月 22, 2022 · 13 分钟 · 2617 字 · yaomingye

SSO 与 JWT+Redis 的定位差异

SSO 与 JWT+Redis 的定位差异:Token格式、管理策略、认证架构三个层次 🤔 一、一个常见的学习困惑 很多开发者在学习鉴权体系时会遇到这样的困惑: 已经理解了 JWT 的三段式结构,知道它是无状态的 Token 格式 也理解了 JWT + Redis 混合方案,知道它能解决 Token 主动撤销的问题 然后听到"微服务用 SSO(单点登录)",去查资料后发现 SSO 也用 JWT 于是产生疑问:JWT + Redis 方案和 SSO 是什么关系?是不是同一个东西的不同叫法?如果不是,区别在哪? 这三个概念确实容易混淆,因为它们都围绕"鉴权"这个话题,但它们解决问题的层次完全不同。下面用三个明确的定义开篇: 概念 本质 解决什么问题 JWT Token 数据格式 Token 如何编码用户信息、如何防篡改 JWT + Redis Token 管理策略(单服务内部) 单个服务如何签发、验证、撤销 Token SSO(单点登录) 认证架构模式(跨服务) 多个服务之间如何共享登录状态 💼 二、从一个具体的业务场景理解差异 假设你所在的公司有三个系统: OA 办公系统(oa.company.com)—— 审批、考勤 CRM 客户系统(crm.company.com)—— 客户管理 BI 报表系统(bi.company.com)—— 数据分析 🏝️ 2.1 没有 SSO 时:每个系统各自鉴权 sequenceDiagram participant U as 用户 participant OA as OA系统 participant CRM as CRM系统 participant BI as BI系统 Note over U,BI: 用户需要分别登录3个系统 U->>OA: 打开OA → 输入用户名密码 OA-->>U: 登录成功 (OA的Token) U->>CRM: 打开CRM → 再次输入用户名密码 CRM-->>U: 登录成功 (CRM的Token) U->>BI: 打开BI → 第三次输入用户名密码 BI-->>U: 登录成功 (BI的Token) 每个系统都有自己独立的用户表、独立的登录接口、独立签发 Token。用户需要在三个系统之间各登录一次。这里的每个系统内部,可能各自使用了 JWT + Redis 管理自己的 Token——但这和"用户只需登录一次"是两个不同的问题。 ...

九月 21, 2022 · 9 分钟 · 1755 字 · yaomingye

JWT 与双令牌机制详解

JWT 与双令牌机制详解:从结构原理到 Java 代码实现 🤔 一、一个登录请求背后的困境 你写完了一个登录接口,用户提交用户名密码,服务端验证通过后创建 Session,把用户信息存进去,返回一个 JSESSIONID 的 Cookie。后续请求自动带上这个 Cookie,服务端从 Session 中取出用户信息——这是最传统的 Session 认证方式。 @PostMapping("/login") public String login(HttpSession session, @RequestBody LoginRequest req) { User user = userService.verify(req.getUsername(), req.getPassword()); if (user == null) { return "用户名或密码错误"; } session.setAttribute("currentUser", user); // 存入Session return "登录成功"; } @GetMapping("/info") public User info(HttpSession session) { return (User) session.getAttribute("currentUser"); // 从Session取 } 这段代码在单机部署时没有问题。但当你部署到 3 台服务器、前面挂了一个 Nginx 负载均衡时,问题就出现了: ...

九月 20, 2022 · 12 分钟 · 2361 字 · yaomingye

JWT + Redis 双令牌鉴权实战

JWT + Redis 双令牌鉴权实战:生产环境下的 Token 主动失效与过期管理方案 🔥 一、一个真实的生产事故 先看一段在中小项目中常见的鉴权代码: // 登录:生成JWT,返回给客户端 public String login(String username, String password) { User user = userService.verify(username, password); return Jwts.builder() .setSubject(user.getId().toString()) .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000)) .signWith(SECRET_KEY) .compact(); } // 拦截器:验证JWT签名和过期时间 public boolean preHandle(HttpServletRequest request, ...) { String token = request.getHeader("Authorization"); Claims claims = Jwts.parserBuilder() .setSigningKey(SECRET_KEY).build() .parseClaimsJws(token).getBody(); // Token签名正确且未过期 → 放行 return true; } 这段代码能跑吗?能。有安全隐患吗?有,而且很严重。 ...

九月 19, 2022 · 19 分钟 · 3916 字 · yaomingye

Spring Security + JWT 企业级鉴权实战

Spring Security + JWT 企业级鉴权实战:从零概念到完整代码实现 阅读前提:本文假设你已经会使用 Spring Boot 写基本的 CRUD 接口。如果你从未接触过 Spring Security,从这篇开始即可。 本文按照"先搞懂概念 → 教程版完整实现 → 生产版逐项升级 → 验证排错“的顺序组织。如果你只想快速跑通一个能用的版本,读完 Part 1 后直接看 Part 2 即可;如果你想理解企业级项目的真实做法,需要完整读完。 Part 1:先搞懂要做什么 在写任何代码之前,先把三个问题搞清楚:认证和授权到底是什么?Spring Security 怎么运作的?JWT 是什么? 一、从一个没有防护的接口说起 假设你用 Spring Boot 写了一个用户管理接口: @RestController @RequestMapping("/api/admin") public class AdminController { @GetMapping("/users") public List<User> listAllUsers() { // 返回系统中所有用户信息 return userService.findAll(); } @DeleteMapping("/users/{id}") public String deleteUser(@PathVariable Long id) { userService.deleteById(id); return "删除成功"; } } 启动项目后,任何人只要知道 URL,就能直接访问这些接口——不需要登录,不需要权限。这在企业生产环境中是不可接受的。 ...

九月 18, 2022 · 23 分钟 · 4761 字 · yaomingye
Cat Radio