关于其他前端常见登录实现+单点登录方案,请见「前端常见登录实现方案 + 单点登录方案
」
前沿
单点登录(SSO),英文全称为 Single Sign On。 SSO 是指在多个应用系统中,用户只需要登录一次,就可以访问所有相互信任的应用系统。
一般同域的SSO,用共享session就可以实现了,常见于各微服务都是自己开发的情况。更普遍的场景是跨域集成的SSO,这时候一般采用标准的CAS方案。
IDP SSO 服务用于解决同一公司不同业务应用之间的身份认证问题,只需要登录一次,即可访问所有添加的应用。此服务可以涵盖用户在公有云和私有云中的双重需求。
几个名词
-
TGT: (Ticket Granting Ticket)这是CAS Server里保存的,用于认证用户已经在CAS登录过
-
TGC: (Ticket Granting Cookie)跟上面的TGT对应,是已经认证过的用户在浏览器里保存的cookie
-
ST: (Service Ticket)这是CAS Server发给应用服务器的凭证,应用服务器再用ST到CAS Server认证
-
Authentication: 【认证】即确认该用户的身份是他所声明的那个人
-
Authorization:【授权】即根据用户身份授予他访问特定资源的权限
CAS认证
Central Authentication Service简称CAS,是一种常见的B/S架构的SSO协议。和其他任何SSO协议一样,用户仅需登陆一次,访问其他应用则无需再次登陆。
CAS是一种仅用于Authentication【认证】的服务,它和OAuth/OIDC协议不一样,并不能作为一种Authorization【授权】的协议。
当前CAS协议包括CAS 1.0、CAS2.0、CAS3.0版本,这三个版本的认证流程基本类似。
👇 下面一个标准的CAS认证流程图:
大致流程:
当用户请求应用服务器提供的某个服务abc,如果没有登录过,那么会返回一个302,跳转到 cas/login?service=abc,在CAS登录后,又会302到abc?ticket=STxxxxx(这里abc就是前面service填的地址),应用服务器用这个ticket到CAS Server认证,如果OK的话,再一次302到abc,完成整个认证过程
IDP 全流程(前后端分离的场景)
现在web应用一般采用前后端分离的架构,通过ajax请求后端服务,这样会无法跳转回原来的静态页面,需要对原有的CAS流程的稍加改造,下面是一个基于CAS实现的IDP系统的完整流程。
👇 应用A 通过 IDP登录
👆 阐述 IDP 发起的单点登录流程:
- 用户访问应用A页面,如:http://a.com/item
- 应用A向A后端请求接口,如:http://a.com/api/item
- A后端检测登录状态,若该用户已登录直接跳至步骤(15. 正常访问),未登录则返回状态码403&跳转链接,如:http://idp.com
- 应用A携带 target_url 重定向到 IDP 登录页面,如:http://idp.com?callback=a.com/item
- 用户在IDP中输入 IDP 的登录手机号并请求验证码
- IDP前端向IDP后端服务请求验证码接口,如:http://idp.com/api/code
- IDP后端别用户手机发送验证码
- 用户填写验证码,并登录
- IDP前端向IDP后端服务请求登录接口,如:http://idp.com/api/session
- IDP后端认证通过后,会生成 TGC&ST,返回给IDP前端
- IDP前端 302 跳转到应用A页面到 SSO URL 地址 redirect_uri并携带ST,如:http://a.com/item?st=xxx
- 应用A页面通过url中的st向应用A后端去认证登录
- 应用A后端再去IDP后端认证登录状态,如:http://idp.com/profile?st
- IDP后端认证通过后,向应用A后端返回用户的信息
- 应用A后端拿到用户信息生成 Token并返回给应用A前端保存
- 最终,用户查看到之前访问的应用A前端,如:http://a.com/item
👇 IDP登录成功,应用B 通过 IDP直接登录
👆 阐述IDP登录成功,应用B 通过 IDP直接单点登录流程:
【大致步骤同应用A 通过 IDP登录,只是少了IDP登录认证的几步】
- 用户访问应用B页面,如:http://b.com/item
- 应用B向B后端请求接口,如:http://b.com/api/item
- B后端检测登录状态,若该用户已登录直接正常访问,未登录则返回状态码403&跳转链接,如:http://idp.com
- 应用B携带 target_url 重定向到 IDP 登录页面,如:http://idp.com?callback=b.com/item
- IDP前端通过session获取TGC向IDP后端服务换取ST,IDP后端认证通过后向IDP前端返回ST
- IDP前端 302 跳转到应用B页面到 SSO URL 地址 redirect_uri并携带ST,如:http://b.com/item?st=xxx
- 应用B页面通过url中的st向应用B后端去认证登录
- 应用B后端再去IDP后端认证登录状态,如:http://idp.com/profile?st
- IDP后端认证通过后,向应用B后端返回用户的信息
- 应用B后端拿到用户信息生成 Token并返回给应用B前端保存
- 最终,用户查看到之前访问的应用B前端,如:http://b.com/item
👇 应用退出登录,IDP退出,所有平台都退出登录
👆 阐述应用退出登录,IDP单点退出登录流程:
- 用户访问应用A页面,点击退出登录,如:http://a.com/logout
- 应用A向A后端请求退出登录接口,如:http://a.com/api/logout
- A后端向IDP后端发送退出登录请求,注销全部TGC&ST
- IDP后端向所有应用后端告知退出事件,如:http://a.com/callback、http://b.com/callback
小结
注意:我们需要对redirect_uri做部分定制并encoding
至此,基于CAS实现的前后端分离的SSO系统开发完毕。如果对流程有问题,欢迎大家讨论