SSO 单点登录会话管理

最近在公司的技术分享会中谈到了SSO相关的知识点,在此再做整理记录。本次分享来自Tate先生,在下只是一个大自然搬运工。其中涉及一些关于单系统登录,多系统分布式登录,微服务系统登录,没有代码,只讨论一些理论基础。

一、背景

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

当今,各互联网公司言必称“生态”,行必是“跨界”,一个公司上的系统平台通常跑着多类业务,就算是单个产品,为了支撑海量用户,产品下的多个业务模块也会按分布式架构去拆分成多个子服务系统来实现,这样一来,各个系统或子服务系统之间的登录验证即有必要做统一的登录和退出处理。比如登录淘宝网之后 ,即可访问淘宝系的各类服务,包括淘宝网、天猫、阿里旅行、聚划算等,同样如果未登录时,在淘宝的各个服务里边点击登录按钮都是跳到同个登录页面。

所以,单点登录的几乎是当下互联网公司信息系统架构的标配,而授权第三方系统访问的开放平台架构是高配。本期以下内容主要讲单点登录的原理和实现思路,后续如有机会再说开发平台架构。

二、单系统登录机制

1、HTTP 无状态协议

HTTP是Hyper Text Transfer Protocol的缩写,顾名思义,这个协议支持着超文本的传输。

对于BS系统,通信机制都是基于http协议,而http是无状态的,即是说每个请求都是独立处理,服务端处理任何一个http请求时,如果只是基于http协议不做其他处理,服务端对于该请求是无知的,它并不知道究竟是A用户A发起的请求,还是用户B发起的请求,自然也就不知道A或者B是否发起了其他请求。任何一个请求都被当成独立的任务,处理完之后就释放了资源,无从追踪。如下图所示:

163317_c3ae_1589819.png

2、登录会话机制

随着时间的推移,人们发现静态的HTML着实无聊而乏味,增加动态生成的内容才会令Web应用程序变得更加有用。于是乎,HTML的语法在不断膨胀,其中最重要的是增加了表单(Form);客户端也增加了诸如脚本处理、DOM处理等功能;对于服务器,则相应的出现了CGI(Common Gateway Interface)以处理包含表单提交在内的动态请求。在这种客户端与服务器进行动态交互的Web应用程序出现之后,HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session。

而想要做到基于HTTP这种轻量级无状态的协议,同时又要让服务器记住发起请求的客户端,就需要双方配合:

1、找个信物让服务端识别这个客户端,一般我们说是会话ID;

2、客户端和服务端各自珍藏这个信物;

3、每次客户端请求服务端时都要带上这个信物;

对于第1点,会话ID一般由服务端产生,只要唯一标识(令牌)这个客户端即可,在JAVA服务端一般用UUID生产一个即可。第2点,双方存储这个会话ID就可以根据自己方便选择存储方式,一般browser客户端可以存在cookie、localstorage等,服务端可以存在内存、数据库(redis、memcache)等。第3点,因为每次http请求都要带上,按照http结构,可以存放的地方可能有url参数、header、cookie,session。

三、登录状态

有了会话机制,那么服务端就能识别每个发过来的请求的是由哪个客户端发起的,而每个客户端之前是否有过请求,请求做了什么处理都可以记住。此时,而登录状态实际上是相当于服务端在存储会话ID的地方同时标明这个会话ID已经登录过了,再对这些已经登录的客户端会话允许他做更多的事情。

1、单系统登录

单系统的登录大致如下图:

170045_Mm8P_1589819.png

客户发起的请求之后,客户端的令牌被记录在当前的ECS机器上的缓存/数据库中,每次请求到达服务端之后,服务端会校验当前的令牌是否允许通过,单系统登录机制相对来说比较简单。因为登录机制的技术点在于令牌配对,服务端如何维护令牌的问题(客户端维护令牌交给终端去处理即可),当涉及到单系统多实例的问题,如下图,单点登录将如何处理?

171329_IbsB_1589819.png

2、多系统登录

随着用户的激增,单系统的架构根本无法满足业务的需求,业界提供的一套较为普遍的解决方案是水平扩展:ECS机器+nginx反向代理来解决请求数激增的问题(成本较低,维护不难)。将这些请求分发到不同的机器去做处理。这样的架构比起单系统的应用架构来说,有了很好的扩展,来解决并发问题。但是这里就存在一个问题:登录信息要存储在哪个机器上?

如果单纯将令牌保存在某一台机器上,服务端处理请求之后,记录这个令牌,同时还要通知其他所有的机器,说:“Hello,XXX用户已经登录了,它的令牌是YYY,你们都记下了,以后XXX用户的请求都不能再拦截了。”

172120_wbw2_1589819.png

除了这种方式之外,也可以利用nginx的特性,将同样的IP转发到同样的机器上(IP哈希),除此之外,还有更好的解决方案吗?很明显,通知各个服务器去更新令牌,将登录信息保存在本地的数据库中,既浪费资源,同时也存在一定的时延,机器之间数据同步往往需要一定的时间(即便利用数据库的同步机制)。IP哈希更不是良策,如今海量用户上网,IP哈希非常容易出现某台机器过载而部分机器又闲适的问题。

我们系统前期采用的高速缓存redis来解决登录问题:

183651_RE3C_1589819.png

将所有的登录信息记录在一个缓存服务器中,客户端发起请求登录之后,令牌保存在缓存服务器的redis上,其他的请求在转发到不同机器的时候,需要去同一个缓存服务器上取令牌信息来判断。客户端退出之后,直接在缓存服务器上清除登录信息,并不需要再去通知其他服务器。其他服务器收到请求查不到令牌之后,再拦截请求,提示登录即可。这种情况基本上不会出现大的时延,没有数据同步的问题,但是弊端则是每次请求要到去另外的服务器去取令牌信息,相当耗,不过相较与其他方案来说,这个方案是较优的,毕竟现在的网速已经越来越快。

除了多系统之外,另外一种多系统则是目前较为流行的“微服务”架构了。核心思想就是:将一个大的应用进行合理拆分成各个微应用,各种好处~不过入坑慎重。

183545_nWYL_1589819.png

在微服务架构中,网关中心会拦截所有的请求,然后再由网关中心做转发到各个应用上去做业务处理,子应用之间也可以相互通信来解决业务问题。并且,子应用是不校验登录信息的,也就是说微服务是信任请求的,它会认为这个请求要么是开放的,要么已经经过网管中心的令牌校验了。所以网关中心上做登录信息的校验,所有请求都必须经过网关中心。

网关心本身就是一个微服务。从上图可以简单的get到一些信息,网关中心有点类似nginx,也在做转发处理,但是因为它也是一个Java应用,我们可以对它做更多事(基于业务的考虑),而nginx更多的可能是作为一个插件来解决一些诸如转发,负载均衡上的问题。当然,nginx 也有自己的优点,两者不能一概而论,因为所做的事也不尽相同,两个也可以相结合使用,不存在谁优谁差的问题。

单点登录大概就是这样的一套解决方案,我们目前也一直在使用后边两种解决方案,后边可能全部拆分成微服务架构也说不定。

 

 

 

转载于:https://my.oschina.net/u/1589819/blog/1480218

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值