- 什么是登录? 正常获取到当前操作的用户信息就是登录
- 为什么需要登录? 某些用户行为需要标注操作到底是谁干的(例如论坛评论)
- 如何登录? 输入经过注册的对应的账号密码
- 为什么需要SSO登录? 紧密相关的平台不应该反复进行登录操作(例如 tce 的各个子平台)
SSO 登录协议
SSO全称 Single sign-on,即单点登录。对于许多相互关联,但是又是各自独立的软件系统,我们往往希望一次登录就可以实现登录所有相互关联其他系统,而不用在切换过程中反复登录。
单点登录的行业标准协议
- Oauth2 : 一种授权标准,允许用户在一个站点向其他站点授予对其资源的有限访问权限,而无需获得其凭证(通常是账号密码)。
不想看概念的同学可以直接拉到后面看场景构造的例子
CAS
概念
CAS是中央认证服务,一种独立开放指令协议,是一种针对万维网的单点登录协议。它的目的是允许一个用户访问多个应用程序,而只需向认证服务器提供一次凭证(如用户名和密码)。
借用一幅大佬的图:
首先需要理解三个东西,暂时看不懂可以直接看下面的例子
简单理解session储存结构如下
| key | value |
|---|---|
| ST | TGC |
| key | value |
|---|---|
| TGC | TGT |
- 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 是一个为 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模型。
区别
- 因为 JWT 并不依赖 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题( CORS ) ,而cookie-session模式则不行。
- JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数,使用 session 则需要频繁查库,造成服务不稳定。
- JWT 最大的优势是服务器不再需要存储 session,使得服务器认证鉴权业务可以方便扩展。但这也是 JWT 最大的缺点:由于服务器不需要存储 session 状态,因此使用过程中无法废弃某个 Token 或者更改 Token 的权限。也就是说一旦 JWT 签发了,到期之前就会始终有效,而session服务可以轻松的删除某个用户的登录态,不需要依赖于其他能力。
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置得比较短。session相比于token往往拥有更长的有效时间。