一、什么是单点登录

单点登录(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的合法性,验证通过后,允许用户访问应用子服务。