SSO 单点登录

424 阅读3分钟

1. is What ?

SSO(single sign on)单点登录是一种验证身份的方案。支持用户通过一次性的身份验证登录其他互相信任的应用系统。

截屏2024-07-03 16.18.27.png

如上图所示,有系统1、系统2、系统3。但是这三个程序都没有设置登录板块,它们的身份验证会统一交给 SSO。SSO 只有登录模块,没有其他业务模块。当系统1、2、3 需要登录时,都会跳到 SSO 系统,在 SSO 系统上完成登录。「很适合在一些大企业的内部系统之间使用」

2. how to work ?

先来说一下一般登录的验证流程。

(1) 用户输入用户名and密码,点击登录。

(2) 客户端把输入的数据传给服务器。

(3) 服务器收到请求后,验证用户名及密码。验证成功的话,服务器会将登录凭证做数字签名并进行加密得到一个 token 返回给客户端,并在自己对应的 session 里记录用户的登录状态为已登录。

(4) 客户端收到 token 后,会把 token 存起来「 cookie or localStorage 」

(5) 后面客户端每次向服务器请求资源的时候都会带上这个 token 进行验证。「 请求头中携带 」

2.1 同域下的单点登录

一般来说,企业的顶级域名只有一个,会通过不同的二级域名来区分不同的系统。举🌰:顶级域名为 baidu.com,其中有一个系统为 app1.baidu.com ,另一个是 app2.baidu.com。想要单点登录就还需要一个系统 sso.baidu.com。

那如何实现在 sso.baidu.com 登录完毕后,其余两个系统也能拿到我们的登录状态?结合一般登录的验证过程来看,需要解决以下两个问题:

  • 🤔 cookie 是不能跨域的,存在 sso.baidu.com cookie里的 token 如何给到另两个系统,让它们发起请求的时候也带上。

  • 🤔 sso、app1、app2 是不同的应用,理论上各自的 session 是隔离存放不共享的。

「 解决方法 」

  • 🥳 sso 登录后,我们可以设置 cookie 的域为顶域,即 baidu.com ,这样所有的子域都可以访问到顶域的 cookie。

  • 🥳 不同系统之间的 session 理论上是不共享的,但是只是理论上哈哈,目前共享 session 的实现方案有很多,比如 Spring-Session、redis、JWT。

这样同域下的单点登录就实现了,但这还不是真正的单点登录。

2.2 不同域下的单点登录

「 大致流程 」

image.png

简单来说就是:

(1) 用户访问 app1 系统,如果没有登录的话,会重定向到 sso 系统。如果 sso 也没有登录的话,会弹出用户登录页。

(2) 用户填写用户名、密码,点击登录 -> sso 系统进行认证后,服务器会把登录状态写入 session,客户端会把服务器返回的 token 存入cookie。

(3) sso 会生成一个 ST「service ticket」,然后会带着 ST 再跳到 app1 系统。

(4) app1 系统拿到 ST 后,向 sso 的服务器发起请求,进行 ST 的验证。

(5) 验证通过后,app1 系统会把登录状态也写入自己的 session ,同时把 token 存进 cookie。

end 当用户又访问 app2 系统时:

<1> 检测到 app2 系统也未登录,会重定向到 sso 系统,发现 sso 系统下已经有登录状态。就会直接带着 ST 跳转回去 app2 系统。

<2> app2 系统会向 sso 服务器发起请求进行 ST 验证。

<3> 验证通过,创建自己的 session ,并存下 token。

上述的 ST 验证这一步是不能舍弃的,防止用户伪造用户信息,直接访问伪造的回调地址。