SSO
SSO 是英文 Single Sign On 的缩写,翻译过来就是单点登陆。顾名思义,它把两个及以上个产品中的用户登陆逻辑抽离出来,达到只输入一次用户名密码,就能同时登陆多个产品的效果。
打个比方,SSO 和咱们去迪士尼玩时购买的通票很像。后端

咱们只要买一次通票,就能够玩全部游乐场内的设施,而不须要在过山车或者摩天轮那里从新买一次票。在这里,买票就至关于登陆认证,游乐场就至关于使用一套 SSO 的公司,各类游乐设施就至关于公司的各个产品。跨域

使用 SSO 的优势很明显:浏览器
就以我厂为例。我厂有两个产品,丁香人才网和丁香园论坛,假如你是我厂用户,确定没法忍受登陆丁香园论坛的时候输入一次用户名密码,登陆人才网又要输入一次用户名密码吧?缓存
假如你是我厂后端,天天任务都饱和的不行,确定没法忍受到人才网开发一套登陆逻辑,到论坛又开发一套登陆逻辑吧?安全
假如你是我厂运维,发现了一个安全隐患须要紧急修复。你确定没法忍受给茫茫多的产品后端都发一封邮件,责令修复吧?万一漏了一个呢?服务器
综合看来,SSO 不只是有用的,并且是必要的。cookie
CAS
SSO 仅仅是一种架构,一种设计,而 CAS 则是实现 SSO 的一种手段。二者是抽象与具体的关系。固然,除了 CAS 以外,实现 SSO 还有其余手段,好比简单的 cookie。
CAS (Central Authentication Service)中心受权服务,自己是一个开源协议,分为 1.0 版本和 2.0 版本。1.0 称为基础模式,2.0称为代理模式,适用于存在非 Web 应用之间的单点登陆。本文只涉及 CAS 1.0,下文中将详细介绍。session
SSO 的演进与分类架构
下面详述一下各类场景下的 SSO,它们之间是逐步升级,逐步复杂化的关系。
1.同域 SSO运维
如图,同域 SSO 是最简单的一种状况。
此时,两个产品都是在一个域名下,单点登陆是很天然的选择。咱们来捋一捋步骤,搞清楚这里的步骤是理解后文的基础,千万不要跳过。
- 用户访问产品 a,向 后台服务器发送登陆请求。
- 登陆认证成功,服务器把用户的登陆信息写入 session。
- 服务器为该用户生成一个 cookie,并加入到 response header 中,随着请求返回而写入浏览器。该 cookie 的域设定为 http://dxy.cn。
- 下一次,当用户访问同域名的产品 b 时,因为 a 和 b 在同一域名下,也是 http://dxy.cn,浏览器会自动带上以前的 cookie。此时后台服务器就能够经过该 cookie 来验证登陆状态了。
实际上,这种场景就是最简单最传统的登陆操做。虽然咱们把产品 a 和 b 人为分开了,但因为它们在同域上,就算当作是同一产品的不一样类目也何尝不可。咱们没有设置独立的 SSO 服务器,由于业务后台服务器自己就足以承担 SSO 的职能。

2.同父域 SSO
同父域 SSO 是同域 SSO 的简单升级,惟一的不一样在于,服务器在返回 cookie 的时候,要把cookie 的 domain 设置为其父域。
好比两个产品的地址分别为 http://a.dxy.cn 和 http://b.dxy.cn,那么 cookie 的域设置为 http://dxy.cn 便可。在访问 a 和 b 时,这个 cookie 都能发送到服务器,本质上和同域 SSO 没有区别。
3.跨域 SSO
能够看到,在上面两种状况下,咱们都没有专门设置 SSO 服务器。可是当两个产品不一样域时,cookie 没法共享,因此咱们必须设置独立的 SSO 服务器了。这个时候,咱们就是经过标准的 CAS 方案来实现 SSO 的。下面咱们就来详细介绍一下:
详解CAS
CAS 1.0 协议定义了一组术语,一组票据,一组接口。
术语:
- Client:用户。
- Server:中心服务器,也是 SSO 中负责单点登陆的服务器。
- Service:须要使用单点登陆的各个服务,至关于上文中的产品 a/b。
接口:
- /login:登陆接口,用于登陆到中心服务器。
- /logout:登出接口,用于从中心服务器登出。
- /validate:用于验证用户是否登陆中心服务器。
- /serviceValidate:用于让各个 service 验证用户是否登陆中心服务器。
票据
- TGT:Ticket Grangting Ticket
TGT 是 CAS 为用户签发的登陆票据,拥有了 TGT,用户就能够证实本身在 CAS 成功登陆过。TGT 封装了 Cookie 值以及此 Cookie 值对应的用户信息。当 HTTP 请求到来时,CAS 以此 Cookie 值(TGC)为 key 查询缓存中有无 TGT ,若是有的话,则相信用户已登陆过。
- TGC:Ticket Granting Cookie
CAS Server 生成TGT放入本身的 Session 中,而 TGC 就是这个 Session 的惟一标识(SessionId),以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。
ST 是 CAS 为用户签发的访问某一 service 的票据。用户访问 service 时,service 发现用户没有 ST,则要求用户去 CAS 获取 ST。用户向 CAS 发出获取 ST 的请求,CAS 发现用户有 TGT,则签发一个 ST,返回给用户。用户拿着 ST 去访问 service,service 拿 ST 去 CAS 验证,验证经过后,容许用户访问资源。
票据之间的关系以下图。注意,PGTIOU, PGT, PT 是 CAS 2.0 中的内容,感兴趣的同窗能够自行了解。

详细步骤
看到这里,是否是又有点晕了?不要紧,下面咱们借助一个简单的场景,再来仔细捋一捋用 CAS 实现 SSO 的详细步骤,顺便加深理解以前提出的概念。
开始!
- 用户访问产品 a,域名是 http://www.a.cn。
- 因为用户没有携带在 a 服务器上登陆的 a cookie,因此 a 服务器返回 http 重定向,重定向的 url 是 SSO 服务器的地址,同时 url 的 query 中经过参数指明登陆成功后,回跳到 a 页面。重定向的url 形如 http://sso.dxy.cn/login?service=https%3A%2F%2Fwww.a.cn。
- 因为用户没有携带在 SSO 服务器上登陆的 TGC(看上面,票据之一),因此 SSO 服务器判断用户未登陆,给用户显示统一登陆界面。用户在 SSO 的页面上进行登陆操做。
- 登陆成功后,SSO 服务器构建用户在 SSO 登陆的 TGT(又一个票据),同时返回一个 http 重定向。这里注意:
- 重定向地址为以前写在 query 里的 a 页面。
- 重定向地址的 query 中包含 sso 服务器派发的 ST。
- 重定向的 http response 中包含写 cookie 的 header。这个 cookie 表明用户在 SSO 中的登陆状态,它的值就是 TGC。
- 浏览器重定向到产品 a。此时重定向的 url 中携带着 SSO 服务器生成的 ST。
- 根据 ST,a 服务器向 SSO 服务器发送请求,SSO 服务器验证票据的有效性。验证成功后,a 服务器知道用户已经在 sso 登陆了,因而 a 服务器构建用户登陆 session,记为 a session。并将 cookie 写入浏览器。注意,此处的 cookie 和 session 保存的是用户在 a 服务器的登陆状态,和 CAS 无关。
- 以后用户访问产品 b,域名是 http://www.b.cn。
- 因为用户没有携带在 b 服务器上登陆的 b cookie,因此 b 服务器返回 http 重定向,重定向的 url 是 SSO 服务器的地址,去询问用户在 SSO 中的登陆状态。
- 浏览器重定向到 SSO。注意,第 4 步中已经向浏览器写入了携带 TGC 的cookie,因此此时 SSO 服务器能够拿到,根据 TGC 去查找 TGT,若是找到,就判断用户已经在 sso 登陆过了。
- SSO 服务器返回一个重定向,重定向携带 ST。注意,这里的 ST 和第4步中的 ST 是不同的,事实上,每次生成的 ST 都是不同的。
- 浏览器带 ST 重定向到 b 服务器,和第 5 步同样。
- b 服务器根据票据向 SSO 服务器发送请求,票据验证经过后,b 服务器知道用户已经在 sso 登陆了,因而生成 b session,向浏览器写入 b cookie。

如图所示,至此,整个登陆流程结束。以后当用户访问 a 或者 b 后,直接会携带 a cookie/b cookie,就不用再向 SSO 确认了。
实际开发时,能够根据 CAS 增长更多的判断逻辑,好比,在收到CAS Server签发的ST后,若是 ST 被 hacker 窃取,而且 client 自己没来得及去验证 ST,被 hacker 抢先一步验证 ST,怎么解决。此时就能够在申请 ST 时添加额外验证因子(如ip、sessionId等)。