SpringBoot 如何实现单点登录(荣耀典藏版) 大家好我是月夜枫。在微服务、多子系统、多后台项目开发中经常会遇到多个系统需要统一登录的需求用户只需要登录一次所有关联子系统全部认证通过无需重复输入账号密码这种方案就是单点登录 SSOSingle Sign On。目前企业内部系统、OA后台、多模块管理平台最主流成熟的方案就是Apereo CAS。在实现单点登录Single Sign-On, SSO功能时有多种技术方案可以选择其中包括使用CASCentral Authentication Service服务。CAS是一种广泛使用的开源单点登录解决方案它允许用户在一个系统中登录后无需再次登录即可访问其他受保护的应用程序或服务。一、CAS 单点登录核心概念1. 什么是 CASCASCentral Authentication Service中心认证服务是 Apereo 开源的企业级单点登录解决方案。核心特点统一认证中心所有子系统统一跳转认证中心登录登录成功后所有客户端共享会话一处登录全部系统免登一处全部登出。2. CAS 架构组成CAS Server 认证服务端独立部署的统一登录中心负责登录页面、账号密码校验、票据Ticket颁发、会话管理、统一登出。所有客户端全部依赖该服务端。CAS Client 客户端我们自己开发的各个 SpringBoot 业务系统不处理登录逻辑所有认证全部交给 CAS 服务端只负责接收、校验服务端发放的票据。3. CAS 完整单点登录流程用户访问客户端A业务系统客户端无登录信息自动重定向到CAS 统一认证中心用户在认证中心输入账号密码完成登录认证中心校验账号合法生成全局唯一TGTTicket Granting Ticket票据存入服务端会话认证中心携带STService Ticket服务票据重定向回到客户端A客户端A携带ST去CAS服务端校验票据合法性校验通过客户端A建立本地会话用户成功访问资源用户再访问客户端B、客户端C无需再次登录直接重定向CAS服务端识别已有TGT直接发放新ST票据客户端校验通过直接访问统一登出在任意系统退出CAS 销毁全局 TGT 票据所有客户端全部失效登出。4. 三种单点登录方案场景对比方案适用场景特点CAS企业内部多系统、后台管理系统、内网平台中心化强认证、统一登录页面、统一权限、原生登出联动OAuth2.0互联网第三方登录、外网应用、多平台授权第三方授权、不统一账号体系、侧重授权而非认证JWT无状态Token微服务前后端分离、无状态分布式接口无状态、无中心认证、不依赖服务端会话二、环境版本说明SpringBoot 2.7.x稳定兼容版和前文项目版本统一Apereo CAS 6.6.x稳定版兼容性最好JDK 1.8多客户端测试客户端1、客户端2 两个独立 SpringBoot 项目模拟多系统端口规划CAS 认证服务端8443CAS官方默认HTTPS端口客户端18081客户端28082三、CAS 服务端搭建统一认证中心CAS官方提供完整原生服务端模板我们直接基于官方 WAR 包改造无需从零开发快速搭建统一登录中心。1. 服务端部署方式下载 Apereo CAS 官方 overlay 项目基于 Maven 构建项目修改登录账号、页面、配置启动服务端默认支持 HTTPS 8443 端口内置简单账号验证可后续对接数据库用户表2. CAS 服务端核心配置修改1修改配置文件cas.properties修改默认账号密码、允许客户端访问地址、票据配置、关闭严格HTTPS校验开发环境。# 服务端访问地址 cas.server.namehttps://localhost:8443 cas.server.prefix${cas.server.name}/cas # 开发环境关闭HTTPS强制校验生产环境必须开启HTTPS tgc.securefalse ticket.securefalse cookie.securefalse # 自定义登录账号密码默认账号 casuser/Mellon cas.authn.static.credentials[0].usernameadmin cas.authn.static.credentials[0].password123456 # 允许接入的客户端服务地址 cas.serviceRegistry.json.locationclasspath:/services2配置允许接入的客户端服务在services目录配置 JSON 文件放行两个客户端域名地址。{ class : org.apereo.cas.services.RegexRegisteredService, serviceId : ^(http|https)://localhost:8081.*, name : Client1-业务系统1, id : 1 }{ class : org.apereo.cas.services.RegexRegisteredService, serviceId : ^(http|https)://localhost:8082.*, name : Client2-业务系统2, id : 2 }配置完成后启动 CAS 服务端访问地址https://localhost:8443/cas/login出现 CAS 官方登录页面输入配置账号admin/123456即可登录成功。四、SpringBoot 客户端整合 CAS下面开始客户端完整接入所有代码格式、依赖、风格完全延续你之前所有SpringBoot文章封装统一配置、拦截器、票据校验多客户端通用代码。1. 客户端统一引入依赖 pom.xml所有业务客户端统一引入cas-client-autoconfig-supportSpringBoot 自动化整合依赖开箱即用无需手动手写原生复杂API。!-- SpringBoot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- CAS 客户端自动化整合依赖 -- dependency groupIdorg.apereo.cas.client/groupId artifactIdcas-client-autoconfig-support/artifactId version2.3.0-GA/version /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency2. application.yml 配置文件客户端18081端口server: port: 8081 # CAS 客户端配置 cas: # CAS统一认证服务端地址 cas-server-url: http://localhost:8443/cas # 当前客户端自身访问地址 service-url: http://localhost:8081 # 开启CAS自动配置 enabled: true # 单点登出 single-logout: true # 校验票据 validate-ticket: true客户端28082端口仅修改自身端口与服务地址其余配置完全一致。server: port: 8082 cas: cas-server-url: http://localhost:8443/cas service-url: http://localhost:8082 enabled: true single-logout: true validate-ticket: true3. 开启CAS客户端自动配置注解在SpringBoot启动类添加EnableCasClient注解自动加载CAS拦截器、票据校验、重定向、单点登出全套功能。import org.apereo.cas.client.boot.configuration.EnableCasClient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication EnableCasClient // 开启CAS单点登录客户端自动配置 public class CasClient1Application { public static void main(String[] args) { SpringApplication.run(CasClient1Application.class, args); } }4. 统一返回结果类 Result复用前文统一格式保持全系列文章代码统一。import lombok.Data; Data public class ResultT { private int code; private String msg; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMsg(操作成功); result.setData(data); return result; } public static T ResultT error(String msg) { ResultT result new Result(); result.setCode(500); result.setMsg(msg); return result; } }5. 获取登录用户信息工具类CAS登录成功后会把登录用户名存入 Request 域封装工具类方便全局获取当前登录用户。import javax.servlet.http.HttpServletRequest; public class CasUserUtil { /** * 从CAS认证上下文获取当前登录用户名 * param request 请求对象 * return 登录账号 */ public static String getLoginUsername(HttpServletRequest request){ return (String) request.getAttribute(_cas_username); } }6. 测试接口编写普通业务接口无需任何登录代码全部认证由CAS拦截器自动处理。import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; RestController RequestMapping(/client) public class ClientTestController { /** * 客户端1测试接口 */ GetMapping(/info1) public ResultString client1Info(HttpServletRequest request){ String username CasUserUtil.getLoginUsername(request); return Result.success(【业务系统1】登录用户 username); } }客户端2同样编写对应测试接口/client/info2。五、完整单点登录流程测试首先启动CAS 8443端口认证服务端依次启动客户端18081、客户端28082直接访问客户端1接口http://localhost:8081/client/info1无登录信息自动重定向跳转到CAS统一登录中心在https://localhost:8443/cas/login输入账号admin/123456完成登录登录成功自动重定向回到客户端1正常返回用户信息直接新窗口访问客户端2接口http://localhost:8082/client/info2无需任何登录操作直接识别已登录凭证直接返回登录用户信息单点登录完成。统一单点登出访问任意系统登出地址http://localhost:8443/cas/logoutCAS服务端销毁全局票据TGT两个客户端全部同时失效再次访问全部需要重新登录。六、开发环境HTTPS问题解决方案CAS官方默认强制HTTPS协议本地开发会出现证书报错、无法访问问题提供两种解决方案1.方案1配置本地自签名证书JDK生成密钥库证书配置到CAS服务端Tomcat完美兼容官方原生流程生产环境标准方案。2.方案2开发环境HTTP兼容改造推荐本地测试修改CAS服务端配置关闭SSL强制校验支持HTTP协议访问无需证书本地开发调试便捷。# 关闭SSL cas.tls.enablefalse七、扩展CAS对接数据库真实用户表原生CAS仅支持静态硬编码账号实际项目需要对接MySQL数据库账号密码登录只需在CAS服务端新增数据库认证配置引入JDBC依赖配置数据库连接即可。# CAS服务端数据库认证配置 cas.authn.jdbc.query[0].urljdbc:mysql://localhost:3306/cas_db cas.authn.jdbc.query[0].userroot cas.authn.jdbc.query[0].passwordroot cas.authn.jdbc.query[0].sqlselect password from sys_user where username? cas.authn.jdbc.query[0].password-encoder-typeBCRYPT实现企业真实账号体系、密码加密校验、数据库用户统一登录。八、CAS 结合 JWT 改造原生CAS基于Session会话微服务分布式场景不适用可进行改造CAS服务端登录成功后不发放传统票据签发JWT令牌各个客户端携带JWT访问接口统一JWT鉴权中心实现无状态分布式单点登录兼顾CAS统一登录中心 JWT无状态微服务优势。九、常见问题与踩坑总结客户端无法重定向CAS服务端检查yml中服务端地址、客户端自身地址配置是否正确端口是否对应。ST票据校验失败服务端未配置客户端服务白名单serviceId正则不匹配未放行客户端地址。跨域、重定向地址不匹配客户端service-url必须和CAS服务端注册的地址完全一致。单点登出不生效客户端配置single-logout: true未开启TGT全局票据未销毁。HTTPS证书不安全报错本地开发关闭SSL校验生产环境必须配置正规域名证书。十、全系列方案总结对比结合前面3篇文章做完整体系总结102 JWT无状态认证前后端分离、微服务接口无状态鉴权无中心。103 OAuth2.0第三方登录互联网项目第三方账号授权登录开放授权场景。104 CAS单点登录SSO企业内部多系统统一登录中心化认证一处登录全部免登。项目选型建议多后台内部系统、OA、统一管理平台 →CAS外网APP、网站第三方登录 →OAuth2.0纯前后端分离接口、微服务权限体系 →JWT学习本就是一个长期积累的过程没有捷径唯有坚持。希望能够真正帮到你学以致用不断提升在自己的领域里越走越远。互动时刻你在项目遇到过什么有趣的问题欢迎在留言区分享你的经验如果这篇文章对你有帮助别忘了点赞、在看、转发三连支持每天分享更多硬核技术干货