SSO 单点登录协议之 CAS与OAuth2

背景

在系统开发初期,系统很少,每个系统都有自己的登录模块,用户直接使用自己的账号进行登录即可。

但当功能不断完善,为了合理利用资源并降低耦合性,往往需要将单系统拆分为多个子系统。

以阿里系的网站为例,一个网站背后有众多的子系统,用户的一次交易或操作往往可能需要十多甚至几十个子系统的协作,如果每个子系统都需要用户进行登录验证,那么用户就需要登录几十次,这显然是不可行的。

那么现在我们面对的情况如下:

  • 当前有多个子系统。
  • 在任何一个子系统登录后,其他系统均无需再次登录。
  • 如何存储证书。
  • 如何验证证书。

一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,用户的一次登录能得到其他所有系统的信任,这就是单点登录。

使用cookie实现SSO

流程

讲解

将证书存储在客户端的cookie中,十分方便,但也带来两个问题

  • cookie的安全性无法保证(对cookie进行加密)。

  • 跨域问题(强制将多个子系统域名设置成一致。(不太现实))

CAS

CAS官网上的标准流程,具体流程如下:

  1. 用户访问app系统,app系统是需要登录的,但用户现在没有登录。
  2. 跳转到CAS server,即SSO登录系统。SSO系统也没有登录,弹出用户登录页。
  3. 用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器中写入SSO域下的Cookie。
  4. SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
  5. app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
  6. 验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

  1. 用户访问app2系统,app2系统没有登录,跳转到SSO。
  2. 根据cookie 查session,发现SSO已经登录了,不需要重新登录认证。
  3. SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
  4. app2拿到ST,后台访问SSO,验证ST是否有效。
  5. 验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

这样,app2系统不需要走登录流程,就已经是登录了。SSO,app和app2在不同的域,它们之间的session不共享也是没问题的。

OAuth2

OAuth2(Open Authorization,开放授权)是为用户资源的授权定义了一个安全、开放及简单的标准,第三方无需知道用户的账号及密码(CAS也不需要知道。),就可获取到用户的授权信息。

主要应用于第三方应用授权登录:在APP或者网页接入一些第三方应用时,时常会需要用户登录另一个合作平台,比如QQ,微博,微信的授权登录,第三方应用通过oauth2方式获取用户信息。

在这里插入图片描述

以微信登录为例:

  1. 用户访问第三方网站,第三方应用需要用户登录验证,用户选择微信授权登录
  2. 第三方应用返回跳转连接(携带redirctUrl),从而发起微信登录授权请求,
  3. 微信服务器拉起用户授权确认页面
  4. 用户授权通过
  5. 微信发送请求到第三方应用redirctUrl(第2步填写redirct_uri参数),返回凭证code与state(第2步自定义)
  6. 第三方应用获取到code之后,根据code获取accessToken
  7. 根据accessToken获取用户信息
  8. 对用户信息进行处理(用户是否第一次登录,保存用户信息,自定义token,session处理等)
  9. 返回结果(步骤1对应url或者重定向到首页)

CAS的单点登录和oauth2的最大区别

保护不同

  • CAS的单点登录是保障客户端的用户资源的安全(应用拿不到用户名密码)。

  • OAuth2则是保障服务端的用户资源的安全(拿到用户信息时需要验证)。

目的不同

  • CAS客户端要获取的最终信息是,这个用户到底有没有权限访问我(CAS客户端)的资源。

  • OAuth2获取的最终信息是,我(oauth2服务提供方)的用户的资源到底能不能让你(oauth2的客户端)访问。

过程不同

  • CAS的单点登录,资源都在CAS客户端这边,不在CAS的服务器那一方。 用户在给CAS服务端提供了用户名密码后,作为CAS客户端并不知道这件事。 随便给客户端个ST,那么客户端是不能确定这个ST是用户伪造还是真的有效,所以要拿着这个ST去服务端再问一下,这个用户给我的是有效的ST还是无效的ST,是有效的我才能让这个用户访问。

  • OAuth2认证,资源都在OAuth2服务提供者那一方,OAuth2客户端是想索取用户的资源。 所以在最安全的模式下,用户授权之后,OAuth2 服务端并不能直接返回token,并重定向送给OAuth2客户端,因为这个token有可能被黑客截获,如果黑客截获了这个token,那用户的资源也就暴露在这个黑客之下了。 于是聪明的OAuth2服务端发送了一个认证code给OAuth2客户端(通过重定向),OAuth2客户端在后台,通过https的方式,用这个code以及另一串OAuth2客户端和OAuth2服务端预先商量好的密码,才能获取到token和刷新token,这个过程是非常安全的。 如果黑客截获了code,他没有那串预先商量好的密码,他也是无法获取token的。这样oauth2就能保证请求资源这件事,是用户同意的,OAuth2客户端也是被认可的,可以放心的把资源发给这个OAuth2客户端了。

总结:所以cas登录和OAuth2在流程上的最大区别就是,通过ST或者code去认证的时候,需不需要预先商量好的密码。

cas 只负责验证用户是否是真的, OAuth2 还负责拿到用户信息


SSO 单点登录协议之 CAS与OAuth2
https://flepeng.github.io/SSO-单点登录协议之-CAS与OAuth2/
作者
Lepeng
发布于
2021年9月2日
许可协议