基于SpringBoot+Shiro+JWT实现的SSO单点登录之核心源码分析
什么是SSO单点登录系统
SSO 单点登录系统是一种在多个相关但独立的软件系统中,用户只需一次登录就可以访问所有相互信任的系统的机制。
实现方式
基于Cookie的方式
同一域下的多个系统共享Cookie来实现单点登录。 例如:存在三个系统A、B、C,C为SSO认证中心,其域名分别为A.ucan.com, B.ucan.com, login.ucan.com , 用户在A登录后,认证系统会在当前浏览器设置一个域为 .ucan.com 的tokenCookie,用户在同一个浏览器中访问B (B.ucan.com)时,浏览器会自动携带这个tokenCookie发送请求到认证系统进行token认证,从而完成登录操作。(注:子域名能访问根域名的cookie)
优点: 实现简单。就是利用浏览器自动携带cookie发送请求的特性实现的。
缺点: 会存在跨域问题。因为不同域名之间不能共享cookie。
基于token令牌的方式
- 用户在认证中心进行登录,用户身份后,认证系统会生成一个加密的令牌(如 JWT)返回给用户。
- 用户携带这个令牌访问其他系统时,其他系统会向认证中心验证令牌的有效性。如果令牌有效,则用户无需再次登录。
优点: 可以跨域使用,适用于不同域名下的系统。令牌可以包含丰富的用户信息,减少对数据库的查询。
缺点: 需要对令牌进行严格的加密和验证,以防止被篡改。
其他方式
基于 SAML(Security Assertion Markup Language)、基于第三方公司的 OAuth2.0/OpenID Connect的方式(没有去研究)。
本文主要介绍基于token令牌实现SSO单点登录原理
项目地址
gitee:springboot-ucan-admin-sso单点登录系统
github:springboot-ucan-admin-sso 单点登录系统
技术栈
- JDK 1.8+
- Tomcat-8.5.63
- SpringBoot2.7.9
- Mybatis-3.5.9
- shiro-core 1.10.1
- Redis
- Mysql 5.7.33
- Layui 2.7.6
- Maven
- JWT
项目安装、配置
- 在本地准备好Java 8运行环境以及Tomcat。
- 安装Mysql数据库,并新建ucan_admin数据库,运行项目中的ucan_admin.sql文件。
- 将项目导入你自己的开发工具 eclipse中。
- 分别修改app-1、app-2、sso-server 的 src/main/resources 目录下的application-dev.yml 文件中的用户名、密码、端口号为你所使用的数据库连接信息。
- 在相应的主机上进行DNS域名解析配置,如:app-1、app-2、sso-server直接在当前windows系统上运行,那么就去 C:\Windows\System32\drivers\etc目录下的hosts文件新增以下内容:
127.0.0.1 localhost
127.0.0.1 ucan.com
127.0.0.1 www.ucan.com
127.0.0.1 login.ucan.com
127.0.0.1 umall.com
127.0.0.1 www.umall.com
然后 cmd 窗口执行:ipconfig /flushdns (linux系统,修改 /etc/hosts文件)
6.安装 Redis。
7.分别在app-1、app-2、sso-server 的 src/main/resources 目录下的application.yml 配置 Redis服务地址/域名、端口号,以及app-1、app-2的SSO系统的相关调用服务地址配置。
- sso-server、app-1、app-2 项目,其端口号分别为:80/8080/8082。(你也可以将app-1/app-2/sso系统分别放在不同的主机上运行,直接使用80端口)
说明:如果sso-server、app-1、app-2 在同一台主机上运行,则可以跳过步骤7 ,否则请根据你的实际情况进行mysql、redis、DNS的配置。
项目运行测试
确认配置信息无误后,分别启动 app-1、app-2、sso系统 ,然后在同一浏览器中输入以下地址进行测试:
http://ucan.com:8080/toLogin
http://ucan.com:8080/index
http://umall.com:8082/toLogin
http://umall.com:8082/index
用户名:admin 密码:123456
用户名:小王 密码:123456
流程解析图
如何实现tokenCookie的跨域?
SSO认证系统生成token后,将其追加到发送认证请求的子系统的 /addToken 服务地址accessToken参数中并进行重定向,再由子系统的 /addToken 服务方法中的setTokenCookie设置tokenCookie(值为sso转发的token值)到子系统的域下,由此完成cookie的跨域。
如何保证JWT的安全性,防止被篡改?
-
设置access token过期时间。
-
创建refresh token(其过期时间要大于等于access token过期时间)。当access token过期的时候,会去校验refresh token的有效性。如果refresh token还在有效期内,则会生成新的access token并更新SSO系统和当前进行认证请求的子系统的tokenCookie;如果refresh token已过期,则直接跳转到SSO认证系统的登录页面,要求重新登录创建新的令牌。
-
access token不要携带敏感信息。
欢迎交流学习!