聊一聊单点登录SSO的来龙去脉和实现逻辑

编程侠 2022-09-09 17:18:18

一、什么是单点登录

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

在初期的时候,我们搭建的是单系统,所有的功能都集中同一个系统上。随着业务的拓展和性能的优化,为了合理利用资源和降低耦合性,我们会考虑把单系统拆分成多个子系统。那么这时候就有一个问题,分的子系统越多,使用起来就越麻烦。例如我每日巡检,所有的子系统我都要登录一下,要记住所有系统的网址、用户名和密码,那就非常麻烦,这时候就有了单点登录的概念,我只需要登录单点登录统一管理系统,然后就可以访问授权的其他子系统,不需要再次登录即可访问。

二、怎么实现单点登录

单点登录的本质就是在多个应用系统中共享登录状态。如果用户的登录状态是记录在 Session 中的,要实现共享登录状态,就要先共享 Session,比如可以将 Session 序列化到 Redis 中(序列化的目的是为了对象可以跨平台存储和进行网络传输),让多个应用系统共享同一个 Redis,直接读取 Redis 来获取 Session。当然仅此是不够的,因为不同的应用系统有着不同的域名,尽管 Session 共享了,但是由于 Session ID 往往保存在浏览器 Cookie 中的,因此存在作用域的限制,无法跨域名传递,也就是说当用户在域名 a.com 中登录后,Session ID 仅在浏览器访问 a.com 时才会自动在请求头中携带,而当浏览器访问 渔民b.com 时,Session ID 是不会被带过去的。实现单点登录的关键在于:如何让 Session ID(或 Token)在多个域中共享。

1、同域名SSO

同域名的单点系统,是最简单的一种框架,比如项目对外共用同一个域名,然后通过haproxy或者nginx等代理软件进行转发,针对不同的上下文映射到不同的子项目里面【注意域名相同但端口号不同的严格意义上不算同域名,他属于跨域的】。我们以nginx转发为例:

两个站点如果在同域下,那么它们之间是可以共享cookie的(cookie不能跨域,当前场景是同域,我们就可以使用)。简单地说就是这种同域下不同站点的sso实现可以通过cookie来实现,当用户访问这个域下面的任意站点时,浏览器都会将这个cookie发送给站点对应的系统。我们以上面nginx里面配置的project1(站点1)和project2(站点2)为例说明。

从站点1登录时,登录成功之后会在浏览器中存储cookie信息,当访问站点2时,由于站点2和站点1在同一个域名下面,所以也会将这些cookie发送给站点2,站点2可以通过cookie信息判断验证实现免登录,这样就能够实现SSO单点登录。

2、不同域名

不同域名,我们首先要进行区分,一种是一级域名相同,二级域名不同,另外一种是一级域名不同。

(1)同父域SSO(同一级域名不同二级域名)

这种在企业里面是比较常见的,使用SSO来管理的子系统,很多公司会分配二级域名进行管理,也便于维护,只需要申请一个一级域名,然后在域名配置那里配置不用的前缀形成二级域名矩阵。

我们以大家常用的百度搜索引擎为例,相同一级域名下面有多个不同前缀的二级域名网站。

同父域 SSO 是同域 SSO 的简单升级,唯一的不同在于,服务器在返回 cookie 的时候,要把cookie 的 domain 设置为其父域。那我们的处理方式就是将 Cookie 的 domain 属性设置为父域的域名(主域名),同时将 Cookie 的 path 属性设置为根路径,这样所有的子域应用就都可以访问到这个 Cookie 了。

(2)跨域的SSO

这种也是比较常见,两个域名都是一级域名,通过SSO来实现系统之间的跳转。我们以阿里巴巴旗下的几个网站为例,不同系统之间使用了不同的域名(当然也有一级域名下面挂多个二级域名的,我们这里不讨论这种场景)。

这种场景,一般建议单独搭建一个单点登录认证系统,也就是我们常说的认证中心(下面的解释就使用认证中心和应用子系统来区分说明)。用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 Token 写入 Cookie。(注意这个 Cookie 是认证中心的,应用的子系统是访问不到的。)

应用子系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心。由于这个操作会将认证中心的 Cookie 自动带过去,因此,认证中心能够根据 Cookie 知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL ,并在跳转前生成一个 Token,拼接在目标 URL 的后面,回传给目标应用子系统。

应用子系统拿到 Token 之后,还需要向认证中心确认下 Token 的合法性,带个参数ST,防止用户伪造。确认无误后,应用子系统记录用户的登录状态,并将 Token 写入 Cookie,然后给本次访问放行。(注意这个 Cookie 是当前应用子系统的,其他应用子系统是访问不到的。)当用户再次访问当前应用子系统时,就会自动带上这个 Token,应用子系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了。

可能说的有点绕,我们来看一下CAS的工作流程,他就是专门来做单点登录的。

访问服务:SSO客户端用户发送请求访问应用子系统

定向认证:用户如果没有登录。重定向跳转到“CAS Server 登录认证中心”进行登录

用户认证:用户填写用户名和密码,认证中心进行账号密码的校验

发放票据:登录认证通过之后认证中心会生成一个随机的ST(Service Ticket)。然后跳转到应用子系统,同时将ST作为参数传递给应用子系统。

验证票据:若用户登录直接携带了票据,认证中心验证票据Service Ticket的合法性,验证通过后,允许用户访问应用子服务。

0 阅读:469

编程侠

简介:一个爱好厨艺的程序员