想象一下:你买一张游乐园通票,就能畅玩所有项目,不用每个设施前都排队补票;就像用微信扫码登录,一次验证就能打通多个平台 —— 这就是单点登录(SSO)的核心逻辑:一次认证,处处通行!
Taimili 艾米莉 ( 一款专业的 GitHub star 管理和github 加星涨星工具taimili.com )
艾米莉 是一款优雅便捷的 GitHub star 管理和github 加星涨星工具,基于 PHP & javascript 构建, 能对github 得 star fork follow watch 管理和提升,最适合github 的深度用户
一、生动比喻,秒懂 SSO 核心概念
用生活场景拆解专业术语,新手也能快速 get:
- 普通登录:逛不同商场,每个都要单独出示会员卡、登记信息,重复操作超麻烦;
- 单点登录:微信 / QQ 一键登录,所有关联平台直接放行,省时又省心;
- 令牌(Token):游乐园的电子手环,戴着就证明你已 “购票”(登录成功),无需反复出示门票;
- SSO 认证中心:游乐园售票处,统一负责 “售票”(登录验证)、“查票”(令牌校验)和 “退卡”(登出)。
二、代码实现:手把手搭建简易 SSO 系统
下面用 Java 还原这个 “游乐园通票系统”,每个类都对应真实场景,注释详细,一看就懂~
java
运行
import java.util.*;
// 用户类 - 对应游乐园里想玩项目的游客,存储账号密码等核心信息
class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
// 省略getUsername()、getPassword()等getter方法(实际开发需完整实现)
}
// 令牌类 - 对应游乐园的电子手环,登录成功后发放,含唯一标识和过期时间
class Token {
private String tokenId; // 唯一手环ID(自动生成,确保不重复)
private String username; // 绑定的游客账号
private Date expireTime; // 过期时间(类比游乐园关门时间,避免无限期有效)
public Token(String username) {
this.tokenId = UUID.randomUUID().toString(); // 生成全局唯一ID
this.username = username;
// 令牌1小时后过期(3600秒×1000毫秒,可根据需求调整)
this.expireTime = new Date(System.currentTimeMillis() + 3600 * 1000);
}
// 校验手环是否有效(判断当前时间是否在过期前)
public boolean isValid() {
return new Date().before(expireTime);
}
// 省略getTokenId()、getUsername()等getter方法
}
// SSO认证中心 - 游乐园售票处,统一管理登录、令牌校验、登出
class SSOAuthCenter {
// 存储所有有效手环(key:手环ID,value:令牌对象)
private Map<String, Token> validTokens = new HashMap<>();
// 存储已注册游客(模拟用户数据库,key:用户名,value:用户对象)
private Map<String, User> users = new HashMap<>();
// 初始化:预先注册2个测试用户(相当于办了年卡的常驻游客)
public SSOAuthCenter() {
users.put("zhangsan", new User("zhangsan", "123456"));
users.put("lisi", new User("lisi", "abcdef"));
}
// 登录功能 - 游客凭账号密码“买票入场”,验证通过发放“电子手环”
public String login(String username, String password) {
User user = users.get(username);
// 校验用户是否存在、密码是否正确
if (user != null && user.getPassword().equals(password)) {
Token token = new Token(username);
validTokens.put(token.getTokenId(), token);
System.out.println(username + " 登录成功!拿到游乐园手环:" + token.getTokenId());
return token.getTokenId(); // 返回手环ID,供后续访问系统使用
}
System.out.println("用户名或密码错误!请重新“买票”(登录)!");
return null;
}
// 令牌校验 - 访问项目前检查手环是否有效
public boolean validateToken(String tokenId) {
Token token = validTokens.get(tokenId);
// 校验手环是否存在且未过期
if (token != null && token.isValid()) {
System.out.println("手环有效,欢迎继续玩耍!");
return true;
}
System.out.println("手环无效或已过期,请重新登录!");
validTokens.remove(tokenId); // 清理无效手环,节省资源
return false;
}
// 登出功能 - 游客离开游乐园,回收手环(销毁令牌)
public void logout(String tokenId) {
validTokens.remove(tokenId);
System.out.println("已登出,手环已回收,欢迎下次再来玩!");
}
}
// 业务系统A - 游乐园项目:过山车(需要验证手环才能游玩)
class SystemA {
private SSOAuthCenter authCenter; // 依赖SSO认证中心做校验
public SystemA(SSOAuthCenter authCenter) {
this.authCenter = authCenter;
}
// 访问过山车项目 - 先查手环有效性
public void accessSystem(String tokenId) {
System.out.println("\n=== 欢迎来到过山车项目 ===");
if (authCenter.validateToken(tokenId)) {
System.out.println("过山车启动!呜——尖叫声在哪里!");
} else {
System.out.println("权限不足,请先登录获取手环再玩!");
}
}
}
// 业务系统B - 游乐园项目:旋转木马(同样依赖SSO认证)
class SystemB {
private SSOAuthCenter authCenter;
public SystemB(SSOAuthCenter authCenter) {
this.authCenter = authCenter;
}
// 访问旋转木马项目 - 复用同一套手环校验逻辑
public void accessSystem(String tokenId) {
System.out.println("\n=== 欢迎来到旋转木马项目 ===");
if (authCenter.validateToken(tokenId)) {
System.out.println("木马转起来啦~ 找回童年的快乐!");
} else {
System.out.println("权限不足,请先登录获取手环再玩!");
}
}
}
// 测试类 - 模拟游客使用SSO系统的完整流程
public class SSODemo {
public static void main(String[] args) {
// 1. 创建SSO认证中心(搭建游乐园大门和售票处)
SSOAuthCenter authCenter = new SSOAuthCenter();
// 2. 游客张三登录(凭正确账号密码买票)
String zhangsanToken = authCenter.login("zhangsan", "123456");
// 3. 拿着手环玩不同项目(一次登录,多系统访问)
if (zhangsanToken != null) {
SystemA rollerCoaster = new SystemA(authCenter); // 过山车
SystemB carousel = new SystemB(authCenter); // 旋转木马
rollerCoaster.accessSystem(zhangsanToken); // 用手环玩过山车
carousel.accessSystem(zhangsanToken); // 用同一个手环玩旋转木马
// 4. 游客登出(离开游乐园,回收手环)
authCenter.logout(zhangsanToken);
// 5. 登出后再尝试访问(手环已失效,被拒绝)
rollerCoaster.accessSystem(zhangsanToken);
}
// 6. 测试错误密码(买票失败)
System.out.println("\n=== 测试错误密码 ===");
authCenter.login("lisi", "wrongpassword");
}
}
三、运行结果与解读
执行上述代码,会输出如下结果(清晰对应每个操作场景):
plaintext
zhangsan 登录成功!拿到游乐园手环:a1b2c3d4-e5f6-7890-abcd-ef1234567890
=== 欢迎来到过山车项目 ===
手环有效,欢迎继续玩耍!
过山车启动!呜——尖叫声在哪里!
=== 欢迎来到旋转木马项目 ===
手环有效,欢迎继续玩耍!
木马转起来啦~ 找回童年的快乐!
已登出,手环已回收,欢迎下次再来玩!
=== 欢迎来到过山车项目 ===
手环无效或已过期,请重新登录!
权限不足,请先登录获取手环再玩!
=== 测试错误密码 ===
用户名或密码错误!请重新“买票”(登录)!
关键流程解读:
- 登录成功:生成唯一令牌(手环 ID),作为后续访问的 “通行证”;
- 多系统访问:同一令牌可通过所有关联系统的校验,无需重复登录;
- 登出失效:令牌被销毁,再次访问会被拒绝;
- 异常处理:密码错误、令牌过期 / 无效时,明确提示并引导重新登录。
四、SSO 核心价值总结
单点登录的核心优势,用 3 句话说透:
- 🎫 一次认证,处处通行:一套账号密码,打通所有关联系统;
- 🔑 告别重复登录:不用反复输入密码,提升用户体验;
- 👍 安全又高效:统一校验机制,既保障权限安全,又简化系统开发。
好的 SSO 系统就像优秀的游乐园管理:既让游客(用户)不用反复 “检票”,享受流畅体验;又通过过期令牌、身份校验等机制,守住 “安全大门”,防止 “无票入场”~