Skip to content

本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com

SSO 的概述

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

SSO 实现机制

要实现 SSO,需要以下主要的功能:

  • 所有应用系统共享一个身份认证系统。统一认证系统是 SSO 的前提之一。认证系统的主要功能是将用户的登录信息和用户信息库相比较,对用户进行登录认证;认证成功后,认证系统应该生成统一的认证标志(ticket),返还给用户。另外,认证系统还应该对 ticket 进行校验,判断其有效性。

  • 所有应用系统(业务系统) 能够识别和提取 ticket 信息。要实现 SSO 的功能,让用户只登录一次,就必须让应用系统能够识别已经登录过的用户。应用系统(业务系统) 应该能对 ticket 进行识别和提取,通过与认证系统的通讯,能自动判断当前用户是否登录过,从而完成单点登录的功能。

如上图所示,图中有 4 个系统,分别是 Application1、Application2、Application3、和 SSO。其中,Application1、Application2、Application3 没有登录模块,而 SSO 只有登录模块,没有其他的业务模块。而当 Application1、Application2、Application3 需要登录时,将统一跳转到 SSO 系统。随着 SSO 系统完成登录,其他的应用系统也就随之登录了。这样就符合单点登录(SSO)的定义。

  • 实际例子 百度地图和百度贴吧都是百度的产品,当用户登录过百度贴吧后,再打开百度地图,系统便自动帮用户登录百度地图,这就属于单点登录。

具体实现方案

普通的登录认证过程

如上图所示,我们在浏览器(Browser)中访问一个业务系统,这个业务系统需要登录,我们填写完用户名和密码后,完成登录认证。这时,我们在这个用户的 session 中标记登录状态为 yes(已登录),同时在浏览器(Browser)中写入 Cookie,这个 Cookie 是这个用户的唯一标识。下次我们再访问这个应用的时候,请求中会带上这个 Cookie,服务端会根据这个 Cookie 找到对应的 session,通过 session 来判断这个用户是否登录。如果不做特殊配置,这个 Cookie 的名字叫做JSESSIONID,其在服务端(server)是唯一的。

同域名下的单点登录

一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:a.com,同时有两个业务系统分别为:app1.a.com 和 app2.a.com。我们要做单点登录(SSO),需要一个登录系统,叫做:sso.a.com。

我们只要在 sso.a.com 登录,app1.a.com 和 app2.a.com 就也登录了。通过上面的登陆认证机制,我们可以知道,在 sso.a.com 中登录了,其实是在 sso.a.com 的服务端的 session 中记录了登录状态,同时在浏览器端(Browser)的 sso.a.com 下写入了 Cookie。那么我们怎么才能让 app1.a.com 和 app2.a.com 登录呢?

Cookie 是不能跨域的,我们 Cookie 的 domain 属性是 sso.a.com,在给 app1.a.com 和 app2.a.com 发送请求是带不上的。sso 登录以后,可以将 Cookie 的域设置为顶域,即. a.com,这样所有子域的系统都可以访问到顶域的 Cookie。

「我们在设置 Cookie 时,只能设置顶域和自己的域,不能设置其他的域。比如:我们不能在自己的系统中给 baidu.com 的域设置 Cookie。」

[不同服务端怎么找到这个 Cookie 对应的 Session 呢?这里就要把 3 个系统的 Session 共享,如图所示。共享 Session 的解决方案有很多,例如:Redis、Spring-Session 等。]

cookie

总结:此种实现方式比较简单,但不支持跨主域名。

不同域名下的单点登录

目前比较常见的还是不同顶域下的多业务系统如何实现 sso 登录,因为不同顶域之间的 Cookie 是无法共享的,这时候就无法用到上面提到的同顶域下的单点登录了。那接下来我们就具体来看一下 CAS 标准的单点登录流程。引用一下别的大佬画的图(参考链接:https://blog.csdn.net/qq_21251983/article/details/52695206):

上图是 CAS 的标准单点登录流程,也是企业中最常用到的 sso 登录标准规范,具体流程如下:

(1)用户访问 app1 系统,app1 系统是需要登录的,但用户现在没有登录。

(2)跳转到 CAS server,即 SSO 登录系统,图中的 CAS Server 就是 SSO 系统。SSO 系统也没有登录态(浏览器端没有 cookie,服务器端没有 session),弹出用户登录页。

(3)用户填写用户名、密码,SSO 系统进行认证后,将登录状态写入 SSO 服务端的 session,浏览器中写入 SSO 域下的 Cookie(全局 cookie)。

(4)SSO 系统登录完成后会生成一个 ST(Service Ticket),然后跳转到 app1 系统,同时将 ST 作为参数传递给 app 系统。

(5)app1 系统拿到 ST 后,从后台向 SSO 发送请求,验证 ST 是否有效。

(6)验证通过后,app1 系统将登录状态写入 session 并设置 app1 域下的 Cookie(局部会话 cookie 和 session,之后与 app1 的会话都会带上这个局部 cookie)。该局部 cookie 也可以理解是一个局部 token。

至此,跨域单点登录就完成了。以后我们再访问 app1 系统时,app1 就是登录的。

接下来,我们再看看访问 app2 系统时的流程。

(1)用户访问 app2 系统,app2 系统没有登录,跳转到 SSO,拿到 sso 域名下的 cookie(全局 cookie)

(2)请求带着全局 cookie 访问 sso,SSO 根据 cookie 判断此时 SSO 已经登录了,不需要重新登录认证。

(3)SSO 生成 ST,浏览器跳转到 app2 系统,并将 ST 作为参数传递给 app2。

(4)app2 拿到 ST,后台访问 SSO,验证 ST 是否有效。

(5)验证成功后,app2 将登录状态写入 session,并在 app2 域下写入 Cookie(如同 app1,这里也是局部 cookie)。

这样,app2 系统不需要走登录流程,就已经是登录了。SSO,app 和 app2 在不同的域,它们之间的 session 不共享也是没问题的。

往期回顾

如何使用 TypeScript 开发 React 函数式组件?

11 个需要避免的 React 错误用法

6 个 Vue3 开发必备的 VSCode 插件

3 款非常实用的 Node.js 版本管理工具

6 个你必须明白 Vue3 的 ref 和 reactive 问题

6 个意想不到的 JavaScript 问题

试着换个角度理解低代码平台设计的本质

回复 “加群”,一起学习进步