弹簧引导基于JWT实现单点登录的案例

  

这篇文章主要介绍spring boot基于JWT实现单点登录的案例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

前言

最近我们组要给负责的一个管理系统 A 集成另外一个系统 B,为了让用户使用更加便捷,避免多个系统重复登录,希望能够达到这样的效果——用户只需登录一次就能够在这两个系统中进行操作。很明显这就是单点登录(Single Sign-On)达到的效果,正好可以明目张胆的学一波单点登录知识。

本篇主要内容如下:

  • SSO 介绍

  • SSO 的几种实现方式对比

  • 基于 JWT 的 spring boot 单点登录实战

注意:

SSO 这个概念已经出现很久很久了,目前各种平台都有非常成熟的实现,比如OpenSSO,OpenAM,Kerberos,CAS等,当然很多时候成熟意味着复杂。本文不讨论那些成熟方案的使用,也不考虑 SSO 在 CS 应用中的使用。

什么是 SSO

单点点说就是:一次登录后可免登陆访问其他的可信平台。比如我们登录淘宝网后,再打开天猫首页可以发现已经是登录状态了。SSO 是一种比较流行的服务于企业业务整合的一种解决方案。

如何实现 SSO

我们都知道目前的 http 协议是无状态的,也就是第一次请求和第二次请求是完全独立,不相关的,但现实中我们的业务逻辑都是有状态的,这样就引入了 cookie-session 的机制来维护状态,浏览器端存储一个 sessionId,后台存储跟该 sessionId 相关的数据。每次向后台发起请求时都携带此 sessionId 就能维持状态了。然后就有了 cookie,浏览器在发送请求时自动将 cookie 中的数据放到请求中,发给服务端,无需手动设置。

然后我们可以考虑考虑实现 SSO 的核心是什么?答案就是如何让一个平台 A 登录后,其他的平台也能获取到平台 A 的登录信息(在 cookie-session 机制中就是 sessionId)。

方案一 共享 cookie

基于 cookie-session 机制的系统中,登录系统后会返回一个 sessionId 存储在 cookie 中,如果我们能够让另外一个系统也能获取到这个 cookie,不就获取到凭证信息了,无需再次登录。刚好浏览器的 cookie 可以实现这样的效果(详见web 跨域及 cookie 学习)。

cookie 允许同域名(或者父子域名)的不同端口中共享 cookie,这点和 http 的同域策略不一样(http 请求只要协议、域名、端口不完全相同便认为跨域)。因此只需将多个应用前台页面部署到相同的域名(或者父子域名),然后共享 session 便能够实现单点登录。架构如下:

spring boot基于JWT实现单点登录的案例

上面方案显而易见的限制就是不仅前台页面需要共享 cookie,后台也需要共享 session(可以用jwt来干掉 session,但是又会引入新的问题,这里不展开).这个方案太简单了,不作进一步说明。

<强>方案二基于回调实现

通过上文可以知道,要实现单点登录只需将用户的身份凭证共享给各个系统,让后台知道现在是谁在访问。就能实现一次登录,到处访问的效果,实在是非常方便的。在会话机制中是共享sessionId,然后多个后台使用同一个会话源即可。这里我们用一种新的基于JWT的令牌方式来实现,不了解JWT的可以看这篇:java-jwt生成与校验,简单来说JWT可以携带无法篡改的信息(一段篡改就会校验失败),所以我们可以将用户id等非敏感信息直接放到智威汤逊中,干掉了后台的会话。然后我们要做的就是将JWT共享给各个平台页面即可。系统架构如下:

春天引导基于JWT实现单点登录的案例

此架构中,业务系统一和业务系统B之间不需要有任何联系,他们都只和SSO认证平台打交道,因此可以任意部署,没有同域的限制。你可能就要问了这样要怎么共享身份凭证(也就是JWT字符串)?这里就要通过url参数来进行骚操作了。

文字总结来说是这样的:JWT存到认证平台前端的localStore(不一定是localStore,饼干,sessionStore都可以),然后业务平台携带自己的回调地址跳转到认证中心的前台,认证中心的前台再将ujwt作为url参数,跳回到那个回调地址上,这样就完成了JWT的共享。

文字很可能看不懂,下面是整个过程的路程图:

春天引导基于JWT实现单点登录的案例

弹簧引导基于JWT实现单点登录的案例