戏说SSO登录全流程

674 阅读8分钟
  • 什么是登录? 正常获取到当前操作的用户信息就是登录
  • 为什么需要登录? 某些用户行为需要标注操作到底是谁干的(例如论坛评论)
  • 如何登录? 输入经过注册的对应的账号密码
  • 为什么需要SSO登录? 紧密相关的平台不应该反复进行登录操作(例如 tce 的各个子平台)

SSO 登录协议

SSO全称 Single sign-on,即单点登录。对于许多相互关联,但是又是各自独立的软件系统,我们往往希望一次登录就可以实现登录所有相互关联其他系统,而不用在切换过程中反复登录。

单点登录的行业标准协议

  • CAS 2 ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的、开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法。
  • Oauth2 一种授权标准,允许用户在一个站点向其他站点授予对其资源的有限访问权限,而无需获得其凭证(通常是账号密码)。
  • SAML 2 作为 SAML 的最新标准, 用来在安全域中交换身份验证数据和授权数据。

不想看概念的同学可以直接拉到后面看场景构造的例子

CAS

概念

CAS是中央认证服务,一种独立开放指令协议,是一种针对万维网的单点登录协议。它的目的是允许一个用户访问多个应用程序,而只需向认证服务器提供一次凭证(如用户名和密码)。

借用一幅大佬的图:

在这里插入图片描述

首先需要理解三个东西,暂时看不懂可以直接看下面的例子

简单理解session储存结构如下

keyvalue
STTGC
keyvalue
TGCTGT
  • TGT:Ticket Grangting Ticket

TGT 是 CAS 为用户签发的登录票据,拥有了 TGT,用户就可以证明自己在 CAS 成功登录过。TGT 封装了TGC所对应的用户信息。

  • TGC:Ticket Granting Cookie

CAS Server 生成TGT放入自己的 Session 数据库中,而 TGC 就是这个 Session 的唯一标识(SessionId),以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。

  • ST:Service Ticket

ST 是 CAS 为用户签发的访问某一 service 的票据。用户访问 service 时,service 发现用户没有 ST,则要求用户去 CAS 获取 ST。用户向 CAS 发出获取 ST 的请求,CAS 发现用户有 TGT(之前登录过),则签发一个 ST,返回给用户。用户拿着 ST 去访问 service,service 拿 ST 去 CAS 验证,验证通过后,允许用户访问资源。

  • session:

session是接入CAS的应用网站自己维护的用户数据库,应用网站会把用户的TGT和TGC存入session,当用户下次登录时,根据用户携带的cookie中的TGC,就可以直接在session中查询用户信息。

让我们构造一种最简单的 CAS 理解场景

在这里插入图片描述

毕业学生信息(TGT) 毕业证号(TGC) 毕业学生证明( ST

小明(用户) A公司(应用网站) 学校( CAS 服务) 公司人才库( session

无法复制加载中的内容

这里有几个点比较特殊:

  • 毕业证明对应ST(ticket),是学校(CAS服务)为A公司(应用网站)专门开具的,在CAS协议中只能使用一次
  • A公司人才库(session)中的数据也有过期时间,过期前小明可以自由应聘(用户每次登录都可以在session中根据TGC查询到对应的TGT),过期后(session中个人信息失效)需要再次去学校申请新的毕业证明。
  • 如果小明未来想去B公司应聘,B公司没有他的个人信息。他也不能使用之前的毕业证明(ST),只能再次请求学校发放新的毕业证明,在学校登录信息未过期前,学校不会要求小明再次出示身份证(登录),而是会直接发放学历证明,B公司也会把小明的个人信息存在自己的人才库中(session)。
  • 所有公司都实现了在学校(CAS服务)证明有效期内不用小明多次出示身份证(CAS登录账号密码),还能拿到了小明的毕业学生信息(用户信息)的能力,即单点登录。

各类SSO服务往往都不会进行用户登录状态的维护,而是只负责用户登录状态的扩散(任何接入服务的应用网站都可以来我这里请求用户信息),登录状态的维护需要接入方自行处理(cookie-session存储/token)。

OAuth

概念

如果你想了解更多OAuth—>

OAuth 是一个为 Web、移动端应用、桌面应用设计的开放的授权标准,旨在让第三方应用能够在无需获取用户密码的前提下得到私有数据, 它是一种授权规范

Oauth2有四种模式,其中code模式是使用范围最广的,下面我们就详细介绍一下: 在这里插入图片描述

让我们构造一种最简单的 OAuth 理解场景

皇帝(资源owner)兵部(授权机构) 军队(资源)

将军(客户端) 调兵令(token) 圣旨(grant/code)

在这里插入图片描述

  • 获取授权许可

普天之下莫非王土,皇帝作为顶级owner拥有整个国家的全部资源,但是有其他用户(将军) 想要使用这些资源(士兵) 时,皇帝需要进行授权。

  • 获取访问令牌

一道圣旨(code) 只能生效一次并具有时效性(eg.三天内前往兵部获取调兵令),用来防止其他人滥用圣旨获取不应得的权利,将军可以在兵部使用圣旨交换调兵令(token)

  • 访问被保护的资源

将军获得调兵令(token) 后,就可以在调兵令的有效期内自由派遣士兵(资源)

  • 刷新访问令牌

如果调兵令(token) 到期失效,将军需要申请新的调兵令(token) ,如下图:

在这里插入图片描述

  • 用户登出

如果将军告老还乡离职,只要告知军队调兵令(token) 失效即可。

授权场景通常和登录场景有相似的流程,所以我们可以使用OAuth规范来处理登录逻辑。

对一个应用来说,只要获取了用户的个人信息,就可以理解为这个用户登录了,SSO服务授权给应用用户的个人信息就可以理解为典型的登录场景。

CAS和Oauth傻傻分不清楚

  • CAS 专注于用户登录, Oauth 专注于授权,但也能干登陆的活
  • CAS用ST ( ticket )获取用户信息只能使用一次
  • OAuth更加复杂,多了一步通过 code 换取 access_token,code只能使用一次,但access_token可以多次获得用户信息
  • OAuth协议约定了 refresh_token/刷新访问令牌 机制,因此可以通过 refresh_token 在后端更新 token,无需再走一遍完整流程,CAS 协议则没有提供这种方案,如果CAS的登录状态过期了就必须重新登录
  • OAuth协议的请求会携带state参数,防范了 csrf 攻击的可能,更加安全

登录状态维护

拿到用户信息,我们需要咋存呢?

cookie-session

  • 接入方服务端自己维护一个session把从sso拿到的用户信息存入
  • 生成一个不可被推测出的复杂字符串session_id作为key
  • 把session_id存入接入方域名的cookie
  • 当请求携带的cookie中有session_id时,我们就能查询出用户信息
  • 如果没有cookie,那就是用户没有登录,可以引导用户走sso流程

就这是经典的cookie-session模型

JWT(Json Web Token)

  • 接入方使从sso拿到的用户信息,生成用密钥加密的字符串token
  • 请求时在(请求头/POST 请求的数据体/url的query)里上带上token,用来验证用户信息
  • 接入方服务端需要根据token上的签名和密钥验证token的真实性
  • 如果请求的token信息过期,需要刷新token

就这是JWT模型

指路大佬文章——>如果你想深入理解token

区别

  • 因为 JWT 并不依赖 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题( CORS ,而cookie-session模式则不行。
  • JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数,使用 session 则需要频繁查库,造成服务不稳定
  • JWT 最大的优势是服务器不再需要存储 session,使得服务器认证鉴权业务可以方便扩展。但这也是 JWT 最大的缺点:由于服务器不需要存储 session 状态,因此使用过程中无法废弃某个 Token 或者更改 Token 的权限。也就是说一旦 JWT 签发了,到期之前就会始终有效,而session服务可以轻松的删除某个用户的登录态,不需要依赖于其他能力。
  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置得比较短。session相比于token往往拥有更长的有效时间。