最近小明遇到一个需求:须要将几个独立的系统(子系统)汇总到一个集中的系统(父系统)当中,当用户在父系统登陆事后,再点击这几个子系统,就能够免登陆跳转到任意一个系统。当时一听,duang~duang~就有不少方案涌进来(吹牛的),但只有下面这个方案获得了leader的确定,现在已经在线上跑着了,接下来给你们复盘一下。前端
看完这个需求,你们是否是第一感受就是:这不就是SSO(单点登陆)系统嘛?程序员
单点登陆(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,可是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登陆时,就能够获取全部系统的访问权限,不用对每一个单一系统都逐一登陆。这项功能一般是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一退出(single sign-off)就是指,只须要单一的退出动做,就能够结束对于多个系统的访问权限。redis
是的,没错,小明接到这个需求之后,总体思路也是按着SSO设想的,可是细想以后,发现不能彻底照搬,要考虑项目的实际状况:好比已知的几个子系统是以前的已经开发好的,不能大动干戈,须要平滑接入父系统,并且根据需求,SSO的功能也不必所有实现,简而言之,就是一个阉割版的SSO。spring
小明只须要实现:用户在父系统帐号密码登陆后,经过点击任意一个子系统的功能按钮(不须要重复输入帐号登陆)可以跳转子系统功能页便可。数据库
一个简单朴素的SpringBoot项目json
说干就干,用户输入帐号密码,请求SSO用户登陆模块进行帐号密码校验,校验经过后创建全局会话,而且返回前端token凭证(我使用的是sessionId),跳转其余系统时携带token,其余系统拿到token后,再调用SSO平台进行token校验,若是校验经过,则用户可在子系统内创建会话,用户跳转系统完成。下面给你们举例SSO跳转一个子系统的时序图:后端
在这里插一嘴哈,我使用的流程图工具是ProcessOn,是一款在线画图工具,很是适合画各类示意图,体验极佳,若是你们想尝试一下,可使用个人邀请连接注册使用~服务器
整个流程图如上面所示,下面主要针对各个功能点进行详细说明。微信
本次会话管理采用的是redis session,spring完美支持redis存储session信息,此外还支持MONGODB\JDBC\HAZELCAST等存储会话方式。经过redis存储session,能够知足集群部署、分布式系统的session共享(固然这些都是后话)。session
pom.xml依赖配置以下
<!--redis 依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--sessions 依赖--> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
application.yml配置redis及session
spring: redis: host: 127.0.0.1 password: 123456 port: 6379 timeout: 1500 database: 0 jedis: pool: max-active: 1000 max-wait: -1 max-idle: 10 min-idle: 5 # 设置session存储类型为redis session: store-type: redis
此时,redis存储会话配置已经完成,但总以为缺乏什么,嗷,原来除此以外,咱们还须要设置session的有效时长,application.yml中的配置以下:
server: servlet: session: # 支持Duration表达式,此时表示120分钟 timeout: PT120M
固然,咱们还须要在Springboot主方法经过@EnableRedisHttpSession
开启redis session
注意:若是上面配置的session有效时长不生效,咱们能够在注解属性上配置session有效时间(不瞒你们,我就是在此处配置才生效的)
@SpringBootApplication // 开启redis session ,而且设置session有效时长 @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 7200) public class XiaoMingApplication { public static void main(String[] args) { SpringApplication.run(XiaoMingApplication.class, args); } }
至此,sso系统的登陆及会话管理就完成啦。接下来看一下与其余系统如何交互。
若是SSO已经登陆 -> 用户点击某个子系统按钮(和负责A系统的人员约定好的连接)发起get请求 -> A系统后端接收到请求 -> 调用SSO系统进行token校验(下面会讲到) -> 创建会话,例如
http://xxx/jump?token=123456
这是一个在地址栏输入的get请求,该接口须要特殊处理,后端拦截器须要放行。
参数 | 说明 |
---|---|
xxx | 此处xxx为域名,jump为系统A提供的接口url地址,能够自定义,须要约定告知 |
token | 返回的校验凭证 |
该接口其实就须要干两件事情:
上面讲到SSO会暴漏一个token校验接口,这一块逻辑很简单,就是拿着token去redis中查找对应的用户信息是否存在。众所周知,小明是一个懒人,为了投机取巧,小明token的生成规则,就是session的id,所以,判断用户是否登陆,其实就是根据sessionId查找redis是否存在会话,此处有亮点。经过查看源码,我发现这个功能,根本不用咱们本身去实现,spring已经想到咱们会用到。
spring提供了一个接口org.springframework.session.SessionRepository
package org.springframework.session; public interface SessionRepository<S extends Session> { S createSession(); void save(S var1); // 这个就是 S findById(String var1); void deleteById(String var1); }
其中S findById(String var1)
就是咱们要调用的方法,这个方法做用就是根据sessionId去会话中心查找会话对象,正是咱们所须要的,咱们只需经过@Autowired
获取,开箱即用~咱们一块儿看一下业务代码:
@Autowired private SessionRepository sessionRepository; @PostMapping("/checkToken") public BaseResponseFacade checkToken(@RequestBody UserLoginVo userLoginVo) { if (Objects.isNull(userLoginVo)) { return ResponseUtil.error(NEED_LOGIN); } String token = userLoginVo.getToken(); Session session = sessionRepository.findById(token); if (Objects.isNull(session)) { return ResponseUtil.error(NEED_LOGIN); } AdverInfo adverInfo = JSON.parseObject(session.getAttribute("adverInfo"), AdverInfo.class); return ResponseUtil.success(adverInfo); }
SSO和子系统的交互文档也贴出来给你们一睹为快
{ "token": "123456" }
参数 | 说明 |
---|---|
xxx/checkToken | xxx为域名,checkToken为营销云平台提供的校验接口地址 |
token | 调用接口凭据 |
返回说明
若是SSO校验经过,则系统A能够与与当前用户创建本地会话,用户正常进入系统
{ "data":{ "XXX":"XXX" }, "errorMsg":"成功", "errorCode":0 }
参数说明
参数 | 说明 |
---|---|
errorCode | 0:表示请求成功 |
errorMsg | 返回码说明 |
XXX | 其余相关信息 |
当SSO后台校验失败时返回参数以下
{ "errorMsg": "NEED_LOGIN", "errorCode": 10 }
参数说明
参数 | 说明 |
---|---|
errorMsg | 错误信息说明 |
errorCode | 错误标志 |
错误码说明
错误码 | 说明 |
---|---|
1 | 系统繁忙 |
10 | 须要用户登陆 |
500 | 服务器内部错误 |
小明设计的简洁版sso就大抵如此,你们能够做为一个sso入门demo来看待😁,若是你们有什么建议或问题,欢迎留言~你们也能够关注微信公众号“程序员小明”获取更多资源~
欢迎关注微信公众号”程序员小明”,获取更多资源。