基于SpringBoot+Shiro+JWT实现的SSO单点登录系统

433 阅读4分钟

基于SpringBoot+Shiro+JWT实现的SSO单点登录之核心源码分析

Shiro认证与授权机制源码分析

什么是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令牌的方式

  1. 用户在认证中心进行登录,用户身份后,认证系统会生成一个加密的令牌(如 JWT)返回给用户。
  2. 用户携带这个令牌访问其他系统时,其他系统会向认证中心验证令牌的有效性。如果令牌有效,则用户无需再次登录。

优点: 可以跨域使用,适用于不同域名下的系统。令牌可以包含丰富的用户信息,减少对数据库的查询。

缺点: 需要对令牌进行严格的加密和验证,以防止被篡改。

其他方式

基于 SAML(Security Assertion Markup Language)、基于第三方公司的 OAuth2.0/OpenID Connect的方式(没有去研究)。

本文主要介绍基于token令牌实现SSO单点登录原理

项目地址

gitee:springboot-ucan-admin-sso单点登录系统

github:springboot-ucan-admin-sso 单点登录系统

逻辑参考:聊聊阿里淘宝SSO跨域登录过程_github

技术栈

  1. JDK 1.8+
  2. Tomcat-8.5.63
  3. SpringBoot2.7.9
  4. Mybatis-3.5.9
  5. shiro-core 1.10.1
  6. Redis
  7. Mysql 5.7.33
  8. Layui 2.7.6
  9. Maven
  10. JWT

项目安装、配置

  1. 在本地准备好Java 8运行环境以及Tomcat。
  2. 安装Mysql数据库,并新建ucan_admin数据库,运行项目中的ucan_admin.sql文件。
  3. 将项目导入你自己的开发工具 eclipse中。
  4. 分别修改app-1、app-2、sso-server 的 src/main/resources 目录下的application-dev.yml 文件中的用户名、密码、端口号为你所使用的数据库连接信息。
  5. 在相应的主机上进行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系统的相关调用服务地址配置。

  1. 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

流程解析图

sso-login.png

如何实现tokenCookie的跨域?

SSO认证系统生成token后,将其追加到发送认证请求的子系统的 /addToken 服务地址accessToken参数中并进行重定向,再由子系统的 /addToken 服务方法中的setTokenCookie设置tokenCookie(值为sso转发的token值)到子系统的域下,由此完成cookie的跨域。

如何保证JWT的安全性,防止被篡改?

  1. 设置access token过期时间。

  2. 创建refresh token(其过期时间要大于等于access token过期时间)。当access token过期的时候,会去校验refresh token的有效性。如果refresh token还在有效期内,则会生成新的access token并更新SSO系统和当前进行认证请求的子系统的tokenCookie;如果refresh token已过期,则直接跳转到SSO认证系统的登录页面,要求重新登录创建新的令牌。

  3. access token不要携带敏感信息。

欢迎交流学习!