SSO实践

在早期的互联网发展时期,用户使用的系统很少,每个系统都有自己的登录系统,用户使用每个系统需要分别进行登录。随着互联网的发展,同一产品下耦合的系统越来越多,这时还需要用户在每个系统都进行登录,这对用户的体验感很不好,这时就需要一种方案可以解决多个相互信任系统需要多次登录的问题,此时单点登录应用而生。

单点登录全称Single Sign On,简称SSO。它的作用是:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的系统。目前有很多种实现方式,本文将介绍3种常见的方式

1、cas单点登录

1.1、什么是CAS

CAS全称 Central Authentication Service,中央认证服务,一种独立开放指令协议,旨在为web应用系统提供一种可靠的单点登录方法。CAS结构体系分为CAS Server与CAS Client,CAS Server负责用户的认证工作,对用户的用户密码进行校验,生成票据。CAS Client负责处理客户端的访问请求,当需要对请求方进行身份认证时,重定向到CAS Server进行认证。其中有3个核心票据需要我们理解,TGT、TGC、ST。

  • TGT(Ticket Grangting Ticket)

TGT为CAS Server为用户签发的登录票据,当用户在CAS Server登录成功后,CAS Server会为该用户生成唯一TGT对象,表示该用户登录成功,TGT封装了Cookie值以及Cookie值对应的用户信息。CAS Server会将生成的TGT对象放在Session中,同时将生成的Cookie,即TGC,返回给浏览器,TGT对象的ID就是cookie的值。TGC-TGT 相当于key-value,可以根据TGC查询TGT。

  • TGC(Ticket Granting Cookie)

TGC,是存放TGT的Session的唯一标识(SessionId),用以查询TGT

  • ST(ServiceTicket)

ST是CAS Server为用户签发的访问某一服务票据。当用户访问某一Service时,Service发现用户没有ST,就会使用户跳转至CAS Server获取ST,此时,如果用户的请求中含有Cookie,则CAS Server会以这个Cookie值(TGC)为key查询session有无TGT,如果有的话,说明用户已登录,则用此TGT签发一个ST返回给用户。用户携带此票据访问Service,Service拿此ST去CAS Server进行验证,如果验证通过,则允许用户访问资源。需要注意的是,同一单点登录系统下,多个系统不共用一个ST,CAS Server会为每个系统生成对应ST,但是TGT与TGC都只有一个。

1.2、认证过程

  • 登录过程
  1. 用户访问系统一,系统检测用户未登录,携带自己的参数跳转到CAS Server进行认证
  2. CAS Server发现用户并未登录,返回登录界面
  3. 用户输入用户、密码进行登录
  4. CAS Server校验用户信息,通过后生成TGT、TGC、ST,将TGT缓存在Session,返回给用户TGC、ST,并重定向到系统一
  5. 用户携带ST访问系统一,系统一请求CAS Server的检验接口对ST进行校验,通过后登录成功,此票据失效
  6. 用户在同域页面携带TGC访问系统二,
  7. 系统检测用户未登录,携带自己的参数跳转到CAS Server进行认证
  8. CAS Server通过以TGC查询到TGT存在,则用此TGT签发一个ST返回给用户,并重定向到系统二
  9. 用户携带ST访问系统二,系统一请求CAS Server的检验接口对ST进行校验,通过后登录成功,此票据失效
  • 登出过程
  1. 用户向系统一发出登出请求,系统一携带TGC向CAS Server发起登出请求
  2. CAS Server根据TGC查询到TGT,销毁TGT信息。同时向所有系统发出登出请求,每个系统的登出接口就是登录接口,只是请求方法不一样,登录是get,登出是post,因此系统需要判断这个接口的请求方法,get就是登录,而post是登出。每一个有效的ticket对应其它系统的一个会话,因此一个ticket会调用一次登出
  3. 各系统接收到登出请求,注销局部会话信息
  4. CAS Serve重定向到系统一的登录界面,用户需要重新进行登录

1.3、最佳实践

网关其实相当于一个cas client,我们以openresty举例子,登录主要过程如下:

1、客户端发起一个普通请求到openresty,openresty检测到会话无效(过期或者未登录),重定向到cas进行登录。

2、重定向时,需要组装location,在cas的登录uri后,需要添加service的参数,这个参数的值是openresty本身的地址+登录的uri,这个值非常重要,会有3个作用。

3、浏览器接收到302的响应会自动跳转,前端其实是不能介入的,这时会引发跨域的问题,需要cas服务端做适配,返回Access-Control-Allow-Origin,但是这也会引发一些问题,HTTP协议具有限制,80以上的浏览器禁止跨域携带cookie。解决的办法很多,架构设计为不跨域的形式或者前端做改造,这里我们采取了前端做改造。

4、输入用户名和密码cas登录登录成功以后,cas会set-cookie,其中包含TGC,并且会302跳转到service的地址,并在参数携带ticket

5、这时openresty接收到这个请求,将会去cas校验ticket的真实性,这时也需要组装service,cas校验ticket时也会校验service是否与登录时一致,如果验证通过,则认为该用户已经登录成功。验证时,cas会返回ticket对应的用户,这里其实就有一个高阶用法,不同系统不同用户的映射,可以在这里做设计。

6、当票据验证成功以后,网关就可以生成会话,同时将会话票据返回到客户端,此时登录成功。

登出也类似,区别在于cas登出以后,会将登录过的系统都登出,调用的接口就是登录时传递的service,不过此时是post请求。

1.4、具体分析

本节具体分析一下1.3中的步骤

1、首先一个请求触发cas,location会是cas服务端的地址

cas-01

2、重定向到cas,参数携带service(我们采用另外一种方式避免跨域,所以这里并不是location,只要知道这是前端做了改造即可)

cas-02

3、此时跳转到cas的登录界面,输入用户和密码以后,进行登录,成功后cas在cookie返回了TGC,并且location跳转了service的地址,里面包含票据

cas-03

4、接着前端跳转了这个地址(需要注意的是这个请求一定是GET,登出时,cas会调用这个接口,为POST)

cas-04

此时网关会校验票据,如果登录成功会生成该系统的会话。

1.5、实际遇到的问题

要实现一个cas单点登录功能,还是稍微复杂的,大体流程很容易懂,但是具体细节有很多,比如如何解决跨域、service的作用、网关和cas的网络问题、有了域名怎么办、网关前面有代理节点怎么办,如果跳转取host,但是前面的节点不传递host,如何登出等等,这些问题都需要在实践中遇到并解决。

2、saml

待补充

3、oauth 2.0

待补充


SSO实践
https://zjfans.github.io/2024/08/04/SSO/
作者
张三疯
发布于
2024年8月4日
许可协议