前端-SSO单点登录方案

4,493 阅读4分钟

一个完整形态的项目和产品,必然绕不开登录,作为一名前端开发工程师,了解单点登录还是非常有必要的。本文就简单分享一下前端所写到的单点登录。

什么是单点登录

概念一大堆,长话短说。单点登录就是指通过用户的一次性鉴别登陆,其他子项目在需要验证用户信息的时候,无需再做登录操作,自动识别登录。

为什么要选择单点登录

  • [🌰] 举个栗子 目前有一个产品,产品下有三个子项目,如果每个子项目都写一遍登录,那么后面维护的时候,开发人员需要打开三处的登录去修改同样的逻辑,这样会发生一种情况就是在改逻辑的时候,如果有另外一个bug着急修改,再回来的时候发现自己不知道改到哪了。(别问,问就是发生在我身上了!)这仅仅是站在前端开发的角度上,维护起来非常累。
  • [ ✔] 使用案例 单点登录在大型网站里使用得非常频繁,例如,阿里旗下有淘宝、天猫等网站,还有背后的成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉。 话不多说直接上图 未命名文件 (2).png 图片有点抽象,不过让我们清晰认知到单点登录要解决的就是,用户只需要登录一次就可以访问所有相互信任的应用系统。

单点登录的实现方式

单点登录的本质就是在多个应用系统中共享登录状态,所以实现单点登录的关键在于,如何让Token在多个域中共享。

1、同域下的单点登录

一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。

比如我有个域名:clnct.cn,同时有三个业务系统分别为:

cpc.clnct.cn
cmk.clnct.cn
ckn.clnct.cn

我们要做单点登录(SSO),需要一个登录系统,叫做:cuc.clnct.cn。

我们只要在cuc.clnct.cn登录,cpc.clnct.cn、cmk.clnct.cn、ckn.clnct.cn也登录了。

实现方式:其实这里就是利用了 二级域名 写 一级域名的 Cookie 。cuc.clnct.cn登录以后,可以将Cookie的域设置为顶域,即.clnct,这样所有子域的系统都可以访问到顶域的Cookie。

此种实现方式比较简单,但不支持跨主域名,局限性限于一级域名是一样的。

2、不同域下的单点登录

同域下的单点登录是巧用了Cookie顶域的特性,如果是不同域呢,比如:下面三个是不同域的

cpc.dun.cn
cmk.qun.cn
ckn.nun.cn

实现方式:我们可以部署一个SSO认证中心,认证中心就是一个专门负责处理登录请求。

未命名文件 (3).png 所有的请求(登录、退出、获取用户信息、当前用户状态)都请求sso系统,sso系统维护用户信息。

此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。

逻辑分析

  • 输入用户名密码,登陆成功,接口返回token 有token,调取换code的接口。 1、接口如果获取的code值为空,清除本地的cookies,再登录;2、如果code有值,将url中的redirectUrl后拼接接口拿到的code 重定向到想要去的页面。

  • 判断域名

这里需用用到
document.domain 获取浏览器的域名

获取到浏览器域名后,匹配当前获取的域名是同域还是来自第三方系统。

如果是同域名,直接将redirectUrl返回,无需携带code接口返回的值。
如果是第三方系统,需要处理redirectUrl。因为可能用户会做登录成功再退出,那么带到登录系统的redirectUrl就会携带code值,我们需要通过js的方法去替换原来的code值。
  • 成功返回redirectUrl 一切流程通了之后,通过 location.replace(redirectUrl) 浏览器跳转返回到重定向页面

目标达成: 子系统在未登录的情况下,点击【登录】按钮,跳转到统一用户中心。统一用户中心判断当前cookies是否有token存在,如果不存在--登录;如果存在就去校验token的合法性(调取code接口),调取code接口成功,重定向到原页面。那么同域下所有的子系统,都无需登录。第三方系统进来的时候,因为做了domian的校验,因此登录成功之后,将code码放在redirectUrl,重定向到第三方系统。

总结一下

这虽然并不是最规范的SSO单点登录。但事实上比起一搜一堆概念性的文章,我认为这仅此是我个人的一种做法,至于逻辑对与错,希望大家给出合理的意见和建议,互相学习。