technology-note/java/web相关/2.spring boot SSO单点登录.md

68 lines
5.6 KiB
Markdown
Raw Normal View History

2019-03-07 19:57:08 +08:00
---
id: '2019-03-01-18-52'
date: '2019/03/01 18:52'
title: 'spring boot 基于JWT实现单点登录'
tags: ['spring-boot', 'SSO', '单点登录', 'jwt']
categories:
- 'java'
- 'spring boot学习'
---
**本篇原创发布于:**[FleyX 的个人博客](http://tapme.top/blog/detail/2019-03-01-18-52)
照例配个图:
![塞尔达,林克](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190301190816.png)
<div style="text-align:center;font-weight:400;font-size:0.9em">我叫林克,不是塞尔达</div>
&emsp;&emsp;最近我们组要给负责的一个管理系统 A 集成另外一个系统 B为了让用户使用更加便捷避免多个系统重复登录希望能够达到这样的效果——用户只需登录一次就能够在这两个系统中进行操作。很明显这就是**单点登录(Single Sign-On)**达到的效果,正好可以明目张胆的学一波单点登录知识。
本篇主要内容如下:
- SSO 介绍
- SSO 的几种实现方式对比
- 基于 JWT 的 spring boot 单点登录实战
**注意:**
&emsp;&emsp;SSO这个概念已经出现很久很久了目前各种平台都有非常成熟的实现比如`OpenSSO``OpenAM``Kerberos``CAS`等,当然很多时候成熟意味着复杂。本文不讨论那些成熟方案的使用,也不考虑SSO在CS应用中的使用。
# 什么是SSO
&emsp;&emsp;单点点说就是一次登录后可免登陆访问其他的可信平台。比如我们登录淘宝网后再打开天猫首页可以发现已经是登录状态了。SSO是一种比较流行的服务于企业业务整合的一种解决方案。
# 如何实现SSO
&emsp;&emsp;我们都知道目前的http协议是无状态的也就是第一次请求和第二次请求是完全独立不相关的但现实中我们的业务逻辑都是有状态的这样就引入了cookie-session的机制来维护状态浏览器端存储一个sessionId,后台存储跟该sessionId相关的数据。每次向后台发起请求时都携带此sessionId就能维持状态了。然后就有了cookie浏览器在发送请求时自动将cookie中的数据放到请求中发给服务端无需手动设置。
&emsp;&emsp;然后我们可以考虑考虑实现SSO的核心是什么答案就是如何让一个平台A登录后其他的平台也能获取到平台A的登录信息在cookie-session机制中就是sessionId
## 方案一 共享cookie
&emsp;&emsp;基于cookie-session机制的系统中登录系统后会返回一个sessionId存储在cookie中如果我们能够让另外一个系统也能获取到这个cookie不就获取到凭证信息了无需再次登录。刚好浏览器的cookie可以实现这样的效果(详见[web跨域及cookie学习](http://tapme.top/blog/detail/2019-03-05-13-41))。
&emsp;&emsp;cookie允许同域名(或者父子域名)的不同端口中共享cookie,这点和http的同域策略不一样http请求只要协议、域名、端口不完全相同便认为跨域。因此只需将多个应用前台页面部署到相同的域名或者父子域名然后共享session便能够实现单点登录。架构如下
![共享session架构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190307185148.png)
&emsp;&emsp;上面方案显而易见的限制就是不仅前台页面需要共享cookie后台也需要共享session可以用`jwt`来干掉session但是又会引入新的问题这里不展开.这个方案太简单了,不作进一步说明。
## 方案二 基于回调实现
&emsp;&emsp;通过上文可以知道,要实现单点登录只需将用户的身份凭证共享给各个系统,让后台知道现在是`谁`在访问。就能实现一次登录到处访问的效果实在是非常方便的。在session机制中是共享sessionId然后多个后台使用同一个session源即可。这里我们用一种新的基于JWT的token方式来实现不了解JWT的可以看这篇[java-jwt生成与校验](http://www.tapme.top/blog/detail/2019-02-28-15-50),简单来说jwt可以携带无法篡改的信息一段篡改就会校验失败),所以我们可以将用户id等非敏感信息直接放到jwt中干掉了后台的session。然后我们要做的就是将jwt共享给各个平台页面即可。系统架构如下
![基于jwt的回调](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190307185751.png)
&emsp;&emsp;此架构中业务系统A和业务系统B之间不需要有任何联系他们都只和SSO认证平台打交道因此可以任意部署没有同域的限制。你可能就要问了这样要怎么共享身份凭证也就是jwt字符串这里就要通过url参数来进行骚操作了。文字总结来说是这样的jwt存到认证平台前端的localStore(不一定是localStorecookiesessionStore都可以),然后业务平台携带自己的回调地址跳转到认证中心的前台认证中心的前台再将ujwt作为url参数跳回到那个回调地址上这样就完成了jwt的共享。
&emsp;&emsp;文字很可能看不懂,下面是整个过程的路程图:
![流程图](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190307193904.png)
相信通过上面的流程图你应该能大概看明白jwt是如何共享了的吧还看不懂的继续看下来下面上一个spring boot实现的简易SSO认证。主要有两个系统SSO认证中心系统A系统A换不同端口运行就是系统A、B、C、D了).
## 实战
### 实现SSO认证中心
&emsp;&emsp;spring boot框架先搭起来由于是简易项目只需要如下依赖