一、单点登录(SSO)概述

单点登录(SSO, Single Sign-On)是一种认证机制,允许用户只需登录一次,即可访问多个相互信任的系统或应用,而不需要为每个系统重复登录。


二、SSO 演进路径

我们可以从以下几个阶段梳理其演进:

1. 基于 Session 的登录共享(早期)

  • 原理:多个系统部署在同一域(或子域),共享 Cookie(Session ID);

  • 代表:JSESSIONID、Token 写入 Cookie;

  • 缺陷

    • 不支持跨域;
    • Cookie 安全性差;
    • 不适用于微服务架构。

2. CAS(Central Authentication Service)

  • 原理:引入认证中心(CAS Server),各系统称为 CAS Client;

  • 流程

    • 用户访问系统 -> 重定向至 CAS;
    • CAS 认证成功发放 Ticket;
    • Client 用 Ticket 交换用户信息;
  • 优点

    • 标准协议,安全性强;
    • 支持登出同步通知;
  • 缺陷

    • 基于 Session,有状态;
    • 跳转流程复杂;
    • 服务注册/信任维护成本高;
    • 不适配现代 SPA 前后端分离模式。

3. Token-Based SSO(JWT/Token)

  • 核心思想:服务端不存储状态,客户端携带身份令牌;

  • 典型实现:JWT(JSON Web Token);

  • 优点

    • 无状态,适合微服务;
    • 易扩展(加密、签名);
    • 支持跨域;
  • 缺点

    • Token 一旦泄露风险大;
    • 不易主动失效(需配合 Redis 黑名单或刷新机制);
    • 前端需妥善管理 Token。

4. OAuth2 / OpenID Connect 标准协议

  • 代表平台:Google、微信、钉钉登录等;

  • 优点

    • 认证与授权分离;
    • 多终端接入支持;
    • 标准化、高度安全;
  • 缺陷

    • 实现复杂,尤其是权限粒度控制;
    • 第三方平台授权变更时要维护兼容性。

5. 微服务网关 + Token + Redis 模式(现代实践)

现代企业系统通常采用如下组合:

组件作用
API Gateway(如 Spring Cloud Gateway)统一入口,进行 Token 验证、权限路由
Auth 服务(Spring Security)登录/登出、签发 Token、权限服务
JWT携带身份信息
Redis(如 Redisson)Token 状态管理、黑名单、刷新机制
微服务(User、Order 等)解耦的业务模块,通过 Gateway 访问

三、SSO 最佳实践指南

✅ 身份令牌设计

  • 使用 JWT,包含以下字段:

    • sub: 用户ID
    • exp: 过期时间
    • iat: 签发时间
    • roles: 权限角色(用于 RBAC)
  • 签名算法建议使用 HS256RS256

✅ Token 安全实践

  • Token 加密传输(HTTPS);
  • 前端使用 HttpOnly Cookie 存储或本地存储(注意 XSS);
  • Token 一旦失效可使用 Redis 进行黑名单控制;
  • 支持 Refresh Token 实现长登录。

✅ 微服务间统一认证

  • 网关统一拦截校验 JWT;
  • 用户信息通过 X-User Header 传递到后端服务;
  • 后端服务不需重复认证,但可基于角色权限授权。

✅ 登出机制

  • 登录状态在 Redis 存储(可配置多端登录);
  • 登出时将 JWT 添加至 Redis 黑名单,或删除登录状态;
  • Token 在过期后自动失效。

✅ 权限控制设计(RBAC)

  • 用户角色与权限粒度控制应后端统一维护;
  • JWT 中应包含角色或权限信息(或仅包含 userId,由后端动态查);
  • 权限校验可在网关或各服务中进行。

四、典型架构图

[Browser / App]|v[API Gateway] --- JWT 验证 + 权限路由|+--- [Auth Service] --> Redis/Redisson -> 签发Token|+--- [User Service]|+--- [Order Service]

五、可选扩展能力

  • ✅ 多端登录管理(每端维护独立 Token);
  • ✅ 支持滑动过期(如 15分钟未操作就过期);
  • ✅ 集成第三方认证平台(微信企业/钉钉 SSO);
  • ✅ 接入 OAuth2 Server(如 Auth0、Spring Authorization Server);
  • ✅ 会话追踪和审计(登录日志、设备管理)。

六、总结建议

方面建议
架构模式网关 + Auth 服务 + Redis + JWT
TokenJWT + RefreshToken + Redis
鉴权粒度网关做粗粒度鉴权,服务内做细粒度控制
异常处理JWT 无效、过期、被撤销统一返回 401
扩展性预留 OAuth2 接入能力;Token 黑名单设计灵活

七、Spring Boot + Spring Security + Redisson + JWT + Spring Cloud Gateway 实现单点登录(SSO)的项目结构和代码示例,适用于微服务环境。

🧱 项目结构(简版)

sso-system/
├── gateway/             # 网关服务:认证拦截、转发
├── auth-service/        # 登录认证服务:签发 Token、登出
├── user-service/        # 示例业务服务:用户信息接口
├── common/              # 公共模块:JWT 工具、DTO、常量等

🔧 1. 公共模块 common

1.1 JWT 工具类

public class JwtUtil {private static final String SECRET = "sso-secret-key";public static String generateToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + 3600_000)) // 1小时.signWith(SignatureAlgorithm.HS256, SECRET).compact();}public static Claims parseToken(String token) {return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();}
}

🚪 2. 网关服务 gateway

2.1 pom.xml(关键依赖)

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.5</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>

2.2 JwtAuthFilter(全局过滤器)

@Component
public class JwtAuthFilter implements GlobalFilter, Ordered {@Autowiredprivate RedissonClient redisson;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token = exchange.getRequest().getHeaders().getFirst("Authorization");if (token != null && token.startsWith("Bearer ")) {try {token = token.replace("Bearer ", "");Claims claims = JwtUtil.parseToken(token);// 黑名单判断if (redisson.getSet("jwt:blacklist").contains(token)) {return unauthorized(exchange);}// 添加用户信息头部String user = claims.getSubject();ServerHttpRequest newRequest = exchange.getRequest().mutate().header("X-User", user).build();return chain.filter(exchange.mutate().request(newRequest).build());} catch (Exception e) {return unauthorized(exchange);}}return unauthorized(exchange);}private Mono<Void> unauthorized(ServerWebExchange exchange) {exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}@Overridepublic int getOrder() {return -1;}
}

2.3 application.yml

spring:cloud:gateway:routes:- id: authuri: http://localhost:8081predicates:- Path=/auth/**- id: useruri: http://localhost:8082predicates:- Path=/user/**redis:host: 127.0.0.1port: 6379

🔐 3. 认证服务 auth-service

3.1 登录控制器

@RestController
@RequestMapping("/auth")
public class AuthController {@Autowiredprivate RedissonClient redisson;@PostMapping("/login")public ResponseEntity<?> login(@RequestBody Map<String, String> req) {String username = req.get("username");String password = req.get("password");// 假设固定账户:admin/123456if ("admin".equals(username) && "123456".equals(password)) {String token = JwtUtil.generateToken(username);redisson.getMap("jwt:token").put(username, token);return ResponseEntity.ok(Map.of("token", token));}return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");}@PostMapping("/logout")public ResponseEntity<?> logout(@RequestHeader("Authorization") String token) {if (token != null && token.startsWith("Bearer ")) {token = token.replace("Bearer ", "");redisson.getSet("jwt:blacklist").add(token);}return ResponseEntity.ok("Logged out");}
}

👤 4. 用户服务 user-service

4.1 控制器

@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/info")public ResponseEntity<?> userInfo(@RequestHeader("X-User") String username) {return ResponseEntity.ok(Map.of("user", username, "role", "admin"));}
}

⚙️ 5. Redisson 配置(通用)

redisson-config.yml

singleServerConfig:address: "redis://127.0.0.1:6379"

Java 配置

@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() throws IOException {Config config = Config.fromYAML(new ClassPathResource("redisson-config.yml").getInputStream());return Redisson.create(config);}
}

✅ 接口调用流程

  1. 调用 POST /auth/login 获取 Token;
  2. 请求头加上 Authorization: Bearer <token>
  3. 访问 GET /user/info 会被 Gateway 验证;
  4. 可调用 POST /auth/logout 退出登录,Token 进入黑名单。

📌 补充说明

  • 安全性增强

    • 加密 Token、添加刷新机制;
    • Redis 维护每个用户的登录态;
  • 权限系统扩展

    • JWT 添加 roles
    • 在 Gateway 或微服务中做 RBAC 检查;
  • 多端登录限制

    • Redis 存储不同端(PC/Mobile)对应 Token;
    • 登出清除端上 Token。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87837.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87837.shtml
英文地址,请注明出处:http://en.pswp.cn/web/87837.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python----OpenCV(图像増强——高通滤波(索贝尔算子、沙尔算子、拉普拉斯算子),图像浮雕与特效处理)

一、 高通滤波 高通滤波是对图像进行卷积操作&#xff0c;以保留图像中的快速变化部分&#xff08;如边缘和细节&#xff09;&#xff0c;同时抑 制低频分量&#xff08;如大面积平坦区域&#xff09;。 应用场景 边缘检测&#xff1a;提取物体轮廓和边界。特征提取&#xff…

oracle 恢复

RECOVER DATABASE USING BACKUP CONTROLFILE “用备份的控制文件推动数据库恢复”。-- 检查控制文件记录的当前SCN (V$DATABASE) SELECT CURRENT_SCN FROM V$DATABASE; -- 检查数据文件头SCN (V$DATAFILE_HEADER) SELECT FILE#, CHECKPOINT_CHANGE# FROM V$DATAFILE_HEADER;-…

京东商品详情SKU数据采集的难点有哪些?

京东商品详情 SKU 数据采集过程中&#xff0c;由于平台的技术防护、数据结构特性及合规性要求&#xff0c;会面临诸多难点&#xff0c;具体如下&#xff1a;一、反爬虫机制的限制京东作为大型电商平台&#xff0c;拥有成熟且严格的反爬虫系统&#xff0c;这是采集时最核心的障碍…

修复手机液晶面板显性横向线性不良定位及相关液晶线路激光修复原理

摘要 手机液晶面板显性横向线性不良严重影响屏幕显示效果&#xff0c;其产生与液晶线路断路、短路或信号传输异常密切相关。精准定位线性不良区域是修复的关键前提&#xff0c;激光修复技术凭借高能量密度与非接触特性&#xff0c;能够有效修复相关液晶线路故障。本文分析显性…

如何解决Spring Boot中@Valid对List校验失效问题

在Spring Boot应用开发中&#xff0c;我们经常需要对传入的请求参数进行校验&#xff0c;以确保数据的合法性和安全性。然而&#xff0c;当我们尝试对列表&#xff08;List&#xff09;类型的参数进行校验时&#xff0c;可能会遇到校验失效的问题。本文将详细探讨这一问题的失效…

云原生环境下部署大语言模型服务:以 DeepSeek 为例的实战教程

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言 随着 DeepSeek、Qwen、ChatGLM 等大语言模型&#xff08;LLM&#xff09;的开放与普及&#xff0c;企业将其私有化部署…

【Spring篇08】:理解自动装配,从spring.factories到.imports剖析

文章目录1. 自动化装配的起点&#xff1a;SpringBootApplication2. 自动化装配的核心机制&#xff1a;EnableAutoConfiguration 和 AutoConfigurationImportSelector3. 自动化配置的注册方式&#xff1a;spring.factories 与 .imports3.1 早期版本&#xff1a;META-INF/spring.…

前置代理重构网络访问的「中转站」

某跨境电商通过前置代理构建账号隔离体系&#xff0c;将亚马逊店铺关联风险降低85%&#xff1b;某企业利用前置代理过滤恶意流量&#xff0c;网络攻击拦截率提升70%。在复杂的网络环境中&#xff0c;前置代理作为客户端与目标服务器之间的「中间枢纽」&#xff0c;正成为跨境访…

乐鑫代理商飞睿科技,2025年AI智能语音助手市场发展趋势与乐鑫芯片解决方案分析

一、市场现状与技术背景进入2025年&#xff0c;AI智能语音助手市场呈现出爆发性增长态势。全球AI应用访问量从2024年初的36亿次激增至76亿次&#xff0c;增幅高达111%&#xff0c;其中语音交互类产品贡献了显著份额。在企业市场&#xff0c;语音技术已从“增值服务”转变为不可…

App爬虫工具篇-Appium安装

之前在另外一篇文章App爬虫工具篇-mitmproxy简单介绍了利用mitmproxy进行接口拦截来获取接口数据。但是很多软件现在都会对相关接口进行加密。如以下我用mitmproxy拦截到接口流量样例: {"raw_data": "EXMcAezXPq/MRC1m2mJIG/EQLisaahfpjPTj9svrxe6yLI8mZTvW4+…

容器与 Kubernetes 基本概念与架构

文章目录 1. 典型环境层次结构2. Kubernetes 生态三大类2.1 核心组件2.2 集群管理工具2.3 生态辅助工具2.4 资源管理关系 3. Docker 容器技术与实践3.1 镜像拉取加速3.2 认证与登录3.3 常用命令3.4 存储挂载方式对比3.5 docker-compose 启动3.6 容器化应用部署示例 4. kind 快速…

Ajax和Axios的初步学习

Ajax 一、什么是 Ajax&#xff1f; Ajax (Asynchronous JavaScript and XML) 是一种无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术。通过在后台与服务器进行少量数据交换&#xff0c;Ajax 可以使网页实现异步更新。 主要特性&#xff1a; 异步性 (Asynch…

C#指针:解锁内存操作的底层密码

C#指针&#xff1a;解锁内存操作的底层密码 在 C# 的世界里&#xff0c;我们习惯了托管代码带来的安全与便捷 —— 垃圾回收器自动管理内存&#xff0c;类型系统严格检查数据操作&#xff0c;就像在精心维护的花园中漫步&#xff0c;无需担心杂草与荆棘。但当性能成为关键瓶颈…

永洪科技荣获商业智能品牌影响力奖,全力打造”AI+决策”引擎

近日&#xff0c;在备受业界瞩目的年度商业智能领域权威评选中&#xff0c;永洪科技凭借卓越的技术实力、深度的客户价值创造能力与前瞻的行业洞察&#xff0c;成功斩获“2025商业智能品牌影响力奖”。这一奖项不仅是对永洪科技市场地位与品牌声量的高度认可&#xff0c;更是对…

在SSM+vue项目中上传表单数据和文件

从前端向后端发送multipart/form-data 类型数据&#xff08;主要用于文件上传或表单提交&#xff09;如发送如下信息&#xff1a;前端代码vue文件&#xff1a;&#xff08;配置了服务器代理&#xff09;<template><div class"content"><el-form :mode…

Python 机器学习核心入门与实战进阶 Day 1 - 分类 vs 回归

✅ 今日目标 理解分类&#xff08;Classification&#xff09;与回归&#xff08;Regression&#xff09;的本质区别掌握两种任务的典型使用场景学会根据任务类型选择合适的模型了解每类模型对应的评估指标 &#x1f4d8; 一、监督学习的两大任务类型 任务类型输出结果典型问…

RPC--自定义注解注册发布服务

自定义的三个注解1、RpcReference这个注解用于修饰类的某个字段&#xff0c;表示这个字段是远程调用的引用下面详细解释下这个字段的定义Document表示这个注解应该被javadoc文档工具记录&#xff0c;生成API文档时使用了该注解的地方会被显示出来Retention表示这个注解的声明周…

Web 3D可视化引擎HOOPS Communicator,高效赋能工业级应用开发!

在数字化转型加速的今天&#xff0c;企业面临着前所未有的挑战——如何高效管理跨平台的设计数据、提升团队协作效率&#xff0c;并加快产品上市速度。HOOPS Communicator作为一款高性能的3D可视化与共享平台&#xff0c;凭借其强大的兼容性、先进的3D渲染引擎和无缝的协作功能…

OceanBase数据库迁移工具介绍和部署

OceanBase数据库迁移工具介绍和部署核心组件迁移支持部署要求单节点部署查看日志OceanBase 迁移服务&#xff08;OceanBase Migration Service, OMS&#xff09;是OceanBase数据库提供的一种支持同构或异构数据源与OceanBase数据库之间进行数据交互的服务&#xff0c;具备在线迁…

栈与队列:算法基础的核心差异

理解栈和队列的异同对打好算法基础太重要了&#xff01;它们都是编程和算法中无处不在的线性数据结构&#xff0c;核心区别在于操作数据的顺序。下面我来帮大家清晰梳理它们的异同点&#xff1a;一、相同点都是线性数据结构&#xff1a;数据元素之间逻辑上呈现“一个接一个”的…