单点登录在任何稍成规模的分布式系统,或者sass,或者中台型的架构中,都是必不可少的,单点登录主要达到的目的是:一处登录,处处登录
这里主要提2种实际生产环境下比较常用的2种业务场景,第一种,产品自身的单点登录需求,比如像下面这张图:
这张图反映的是一些类似sass系统或者业务中台类似的体系架构,一个系统的各个产品均能通过一个统一的登录入口进入,然后由各个产品应用图标,再进入各自的模块产品
第二种业务场景是,当涉及到和第三方应用进行对接的时候,第三方系统希望共享与本系统的部分用户信息,通俗来讲就是,本系统的某些产品对接了第三方平台的应用,客户端希望能够在本系统和外部系统之间来回切换,而不用重复在2个平台之间进行登录,以下图进行理解:
本篇以上面的2个需求点入手,从业务的角度引申到实际方案的实现进行一些探讨和经验的分享
1、cookie实现方案
这是一种最简单的单点登录实现方式,是使用cookie作为媒介,存放用户会话凭证
简而言之,用户登录父应用之后,应用返回一个cookie(或加密的cookie),当用户访问子应用的时候,携带上这个cookie,授权应用拿到cookie并进行校验,校验通过则允许该用户访问当前应用
cookie信息通常可以在浏览器中进行查看,如果后端没有做任何的处理,通常以jsessionid进行展示
我们知道,对于sass平台或类似的系统,父应用或者顶级应用在登录成功后,会进入主域名,比如taobao.com,然后再从主域名进入各个子系统,即二级域名下,如果是同域的情况下,cookie的会话信息是可以共享(或者传递)的,这样的话,当主域名的用户关键信息存至cookie后,其他子域下的系统就可以拿到当前cookie的信息进行解析并获取用户信息
cookie方案可使登录后的用户在各个应用之间正常的访问,当然,在实际生产中,同一个用户在各个应用之间的切换与访问也是有前提条件的,那就是权限体系的认证,即至少保证当前用户拥有要访问应用的权限
在小编过往的项目中,sass平台有一个统一用户系统,所有访问系统的用户均需在用户的体系下存在,然后在用户系统中进行对使用其他应用的访问权限进行统一配置(赋权)之后,才能进行各个应用之间的切换,从具体的实现来说,主要分为如下步骤:
cookie方案在实际实施的时候,被很多人吐槽的点有2个,容易被截取(不够安全),不够轻量级,就这2点,就足够成为分布式应用下如何高效进行会话传输被舍弃的因素了,因此在本人经历的项目以及从主流的解决方案下,token方案开始越来越被很多互联网公司接受
token的实现相对简单,前后端交互方便,存储的安全性可以根据采用的加密技术提升安全性,主流的实现像:springsecurity , jwt+shiro 等,都是不错的实现思路
具体来说,token的实现方案和cookie的实现方案本质不同点在于会话信息的传输上有所不同,其基础的架构体系并没有太大的差别,但token解决这个问题更灵活的地方在于,
总的来说,业务层面的操作和上面cookie方案中的没有本质差别,只体现在具体的实现上,这样以来,用户中心的总体业务层的规划可按如下理解
关于token的具体落地实现方案,有兴趣的同学可以参考我之前的2篇文章:springboot+shiro实现安全认证以及基于springcloud实现安全认证
总结一下,以上两种实现方案适合初具中台规模或者类sass系统的平台,拥有独立的用户中心体系,需要通过独立的用户中心进行其他应用的资源配置,认证,授权等,在这种架构下,采用单点登录具有它存在的价值和意义,毕竟单独把用户中心拆分成独立的微服务,是需要投入一定的技术和人力成本的
当sass系统做大了之后,比如像支付宝,很多其他第三方应用为了对接支付宝的支付体系,举例来说,当我们在美团下单时,提示我们选择支付宝支付的时候,需要跳转到支付宝的一个认证页面进行认证,只有认证通过之后,才能进行支付
这里涉及到一个用户信息的转换问题,可以理解为认证中心,这个认证中心具备用户认证,以及分发凭证的功能,认证中心的实现我们无从得知,但是可以参考springsecurity的认证功能实现,和oauth2那一套大体类似
我们这里探讨的是一种更通用的基于sass平台或者中台模式的实现,即假定通过我们自身的sass平台跳转到第三方平台的应用系统,或者由第三方应用系统跳转到我们自身的sass系统,该如何实现的问题
方案一:第三方应用作为自身平台的一个应用注册
第三方系统作为一个应用,集成到自身的sass平台。用户以自身平台为入口登录并跳转至第三方系统
同域
当自身平台与第三方系统同域时,第三方系统能够直接通过Cookie获取本平台用户会话信息(token),通过调用本平台提供的相关dubbo接口即可获取用户信息,进而同步用户至第三方系统并实现免登录
同域情况下,第三方应用可以拿到本平台的cookie信息,拿到之后,进一步调用本平台提供的dubbo接口获取用户的数据,一般来说,这种情况下,第三方系统为了更好的管理用户数据,需要和本平台的用户信息进行适配,对第三方系统来说,只需要自己的系统用户表中做一个映射即可达到目的
非同域
当自身sass平台与第三方系统非同域时,第三方系统就无法通过浏览器Cookie信息获取自身sass平台用户会话信息,这时候可以借助中间件,通过中间件传递用户信息
方案二:将本平台作为一个应用注册到第三方系统
此种方案需要提供本平台用户登录的URL给第三方系统,同样需要考虑同域和非同域的情况
同域
需要根据情况实现特殊单点登录SPI服务
当本平台与第三方系统同域时,第三方系统将会话信息(识别用户即可)写入浏览器Cookie,随即跳转至本平台登录页面,特殊单点登录SPI服务(需要实现)读取Cookie中的用户信息,对用户进行同步、免登录等。
通常这种方式涉及到2个系统的对接,需要对方的开发人员提供一些配置信息,比如本系统提供登录的URL,而第三方系统提供登录回调的URL,这样的话在本系统完成登录的逻辑之后才知道调回的路径
但是本人经历的项目中是这么做的,提供一个基于spi实现的一个验证token的jar包,这个jar包可立即为一个简单的工程,该工程实现了一个关键的接口,在该接口中实现的逻辑是,校验token,解析出用户信息,然后执行自动登录,并跳转url
很明显,这个jar包是作为连接本系统和第三方系统用的
非同域
当本平台与第三方系统非同域时,第三方系统无法将会话信息写入浏览器Cookie,这时候需要实现中间件部署在与本平台同域环境中,第三方系统先跳转至中间件页面,通过中间件将用户信息写入Cookie,最后跳转至UYUN平台登录页面,特殊单点登录SPI服务(需要实现)读取Cookie中的用户信息,对用户进行同步、免登录等。
图中的中间件可理解为一个需要通过消息中间件实现用户信息传递的一个工程,该工程部署在和本平台同域的环境上
方案三:CAS单点登录
这种方案的实现网上可以参考的资料非常多,也是当下比较简单的一种实现,开发者只需要对cas证书做配置,这里不再赘述了