SSO介绍
SSO(Single sign-on):在多个相互信任的应用系统中,只需要登录一次,就可以访问其他的应用系统。
SSO的实现方式
无论是SSO还是普通登录,它们的实现都是基于Cookie-Session模式的。该模式的基本流程如下:
从上面可以看出,cookie 是服务端生成发送到浏览器端的。浏览器端将 cookie 存储在本地,并且在之后每次的用户端 HTTP 请求头中都附带的一小段数据。
而且cookie 是跟域名关联的,其对应浏览器所请求的域名。
cookie有如下的重要属性:
Name:单条 cookie 信息的 key 值,我们通常也是通过这个 key 值设置和获取存储在 cookie 中数据。
Value:我们所说的cookie的值。
Expires/Max-Age:此条 cookie 记录的到期时间。
Domain:此条 cookie 的作用范围。我们知道域名是分多个级别的,如:顶级域名、二级域名、三级域名等等。domain 属性是指可以访问该 cookie 的域名。如果设置为 '.baidu.com',那么末尾是 '.baidu.com' 结束的域名都可以访问到这个 cookie,要注意必须是 '.' 开头。这产生了一个效果,那就是 '.baidu.com' 下属的子域名也可以访问这个 cookie,例如: '.tieba.baidu.com'。
1、各子系统在相同的域名下
一般情况下,企业只有一个二级域名,然后通过三级域名区分不同的系统。比如公司有个二级域名叫做:.bl.com,同时有两个业务系统分别为:.app1.bl.com和 .app2.bl.com,以及一个登录系统:.sso.bl.com。
我们要实现只在 .sso.bl.com登录,.app1.bl.com和 .app2.bl.com也就登录了。
例如,用户通过浏览器登录 .sso.bl.com系统,根据cookie-session模式可知, .sso.bl.com 的服务端的session中会记录登录状态,同时浏览器会保存cookie信息,其中cookie的Domain属性为 .sso.bl.com。
如果我们想让其他两个系统 .app1.bl.com 和 .app2.bl.com 登录,需要解决两个问题:
浏览器的cookie的Domain属性是.sso.a.com,在给app1.bl.com和app2.bl.com发送请求是带不上的。
sso、app1和app2是不同的应用,它们的session存在自己的应用内,是不共享的。
好在解决这两个问题是比较简单的。针对第一个问题,sso登录以后,可以将cookie的域设置为二级域名 .bl.com,这样所有子域的系统都可以访问到二级域的 cookie。针对第二个问题,解决方法就是 seesion共享。
2、各子系统属于不同的域
若各个子系统属于不同的域,那么它们之间的 cookie 是无法共享的。因此需要一种新的解决方案,目前单点登录的标准流程就是 CAS。
CAS
Central Authentication Service ——— 中央认证服务,是 Yale 大学发起的一个企业级的、开源的项目,旨在为 Web 应用系统提供一种可靠的 SSO 解决方案。
标准的CAS登录流程如下:
第一次访问app:
用户访问app系统,app系统是需要登录的,app验证cookie和session发现用户没有登录,要求用户重定向到 CAS Server,同时要携带service参数。
跳转到CAS Server,CAS Server系统发现用户也没有登录本系统,弹出用户登录页。
用户填写用户名、密码,CAS Server系统进行认证后,CAS Server生成一个该用户的SSO session存放到本地session中,并生成一个SSO session id,即TGT。最后重定向返回一个CASTGC(放在cookie内)给用户浏览器,这个TGC中包含了TGT的值。
CAS Server系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
验证通过后,app系统将登录状态写入session并设置app域下的Cookie,再返回给浏览器。
用户发起请求,带上cookie,app系统校验cookie和session。通过后,返回app正确的内容给浏览器。
第二次方法app:
用户发起请求,并带上 Cookie 中的 JSESSIONID 给 app 服务端。
app 服务端 使用 JSESSIONID 与 Session 中存储的数据进行校验。
校验通过,返回正确的内容,展示 app 。
再app登录成功的情况下,第一次访问app2:
访问 app2 服务地址,app2 请求未通过认证,重定向至 CAS Server 地址。
访问 CAS Server 地址,发送认证请求,带上 TGC 信息。
CAS Server 通过 TGC中的TGT 去查找 SSO Session 的信息进行认证。
认证通过,生成票据 ST 重定向至 app2 的服务地址。
app2 服务 携带 ST 向 CAS Server 进行认证。
CAS Server 认证成功,返回通过的响应。
app2 服务拿到成功的响应后,设置 Session,并重定向至 app2 的地址,并设置 Cookie MOD_AUTH_CAS_S。
用户浏览器 发起请求,带上 Cookie 中的 MOD_AUTH_CAS_S ,发送给app2 服务进行校验。
app2 服务使用 MOD_AUTH_CAS_S 与 Session 中存储的数据进行校验。
校验通过,返回正确的内容,展示 app2。
CAS重要字段
TGT
CAS Server 创建TGT,存放在 CAS Server的 Session 里面,根据用户信息签发的。简单来说,TGT 是 SSO Session 的 ID。
TGC
创建 TGT 的同时,生成 TGC。通过 CAS Server 的 response header 的 set-cookie 字段设置 TGC,其中包含了 TGT 的信息。
ST
根据 TGT 签发的 ST,是 CAS 为用户签发的访问某一 service 的票据。在CAS Server 创建 TGT 后,生成一个 ST 将其添到重定向地址后。
为了保证ST的安全性:ST 是基于随机生成的,没有规律性。而且,CAS规定 ST 只能存活一定的时间,然后 CAS Server 会让它失效。而且,CAS 协议规定ST只能使用一次,无论 Service Ticket 验证是否成功, CASServer 都会清除服务端缓存中的该 Ticket ,从而可以确保一个 Service Ticket 不被使用两次。