在多个系统中,用户只需要登录一次,就可以访问所有相互信任的应用系统,这就是单点登录。

单点登录场景

下面介绍单点登录在同域和不同域的情况下的实现。

同域

这里的同域指二级域名相同,如xxx.com,应用系统A为a.xxx.com,应用系统B为b.xxx.com,然后单点登录系统为sso.xxx.com。

我们在sso.xxx.com中登录,然后a.xxx.com和b.xxx.com也登录了。那么如何做到呢?

sso登录后,可以利用cookie的特性,将cookie的domain设置为二级域名,即.xxx.com,这样a.xxx.com和b.xxx.com都可以读取到此cookie,sso服务端保存了此cookie对应的session,利用session共享技术,系统A和系统B都可以用此cookie进行通信。即实现了最简单的单点登录。

这个方式有一些缺点:

  • 子系统必须都在同一个二级域下,不然获取不到cookie
  • 用户信息保存在cookie中是不安全的

不同域


不同域有三种实现方式,JWT,CAS和OAuth2.0,其中CAS一般是公司内部使用,OAuth2.0可以提供给第三方用户登录。当然同域也可以使用这些方式,选择最适合自身需求的即可。

JWT

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
JWT是一个开放标准 RFC 7519,可以在各方之间使用JSON安全的传输信息,此信息可以通过数字签名进行验证和信任。

JWT可以用于授权和信息交换。

JWT的结构

典型的JWT的格式xxxxx.yyyyy.zzzzz,包含三部分:

  • Header

header包含两部分: type 和 签名算法。此JSON使用Base64Url处理后即为JWT的第一部分。

  1. {
  2. "alg": "HS256",
  3. "typ": "JWT"
  4. }
  • Payload

包含claims(实体和其他数据的声明),有三种类型registered, public, and private claims。此JSON使用Base64Url处理后即为JWT的第二部分。

  1. {
  2. "sub": "1234567890",
  3. "name": "John Doe",
  4. "admin": true
  5. }

注意:对于签名令牌,此信息虽然可以防止篡改,但任何人都可以读取。除非加密,否则不要将敏感信息放入到Payload或Header元素中。

  • Signature

要创建签名部分,必须采用编码的Header,编码的Payload,秘钥,Header中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,将按以下方式创建签名:

  1. HMACSHA256(
  2. base64UrlEncode(header) + "." +
  3. base64UrlEncode(payload),
  4. secret)

签名用于验证信息是否被篡改,在使用私钥签名的情况下,可以验证JWT的请求方是否是声明的请求方。

最后生成的格式如下:
SSO 单点登录 - 图1

JWT流程

  1. ![](https://cdn.nlark.com/yuque/0/2019/png/129208/1575288893225-bda0ad2b-c893-4674-9fb6-d8099e644d0b.png#align=left&display=inline&height=190&originHeight=571&originWidth=1500&size=0&status=done&style=none&width=498)
  1. client请求认证服务器
  2. 认证服务器返回access token给client
  3. client使用access token和资源服务器通信

access token一般放在Authorization header中,可以使用Bearer验证方案。

  1. Authorization: Bearer <token>

参考:https://jwt.io/introduction/

CAS

CAS provides enterprise single sign-on service for the Web。

SSO 单点登录 - 图2

上图是使用CAS协议的单点登录流程图,想了解更多的可以直接去CAS官网。具体流程如下:

  1. 用户访问app系统,但是app系统没有登录
  2. 重定向到CAS系统,即SSO登录系统
  3. 用户在SSO系统输入用户名密码进行登录
  4. 登录成功后将登录状态写入SSO服务器的session,以及浏览器的cookie(sso域下)。SSO系统会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
  5. app系统拿到ST去SSO服务器验证ST有效性
  6. 验证通过后,app系统将登录信息写入session以及app域下的cookie

至此,app系统已经完成了单点登录,可以正常进行访问。下面,我们再来看看访问app2时的流程:

  1. 用户访问app2,app2没有登录,跳转到SSO
  2. SSO已经登录,不需要重新登录
  3. SSO生成ST,返回至App2,并将ST传给app2
  4. app2拿到ST去SSO服务器验证ST有效性
  5. 验证通过后,app2系统将登录信息写入session以及app域下的cookie

这样app2也可以正常访问了。

OAuth2.0

OAuth 2.0 is the industry-standard protocol for authorization.
OAuth 2.0是用于授权的行业标准协议。协议号为 RFC 6749。允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。

四种角色

  • 资源所有者:能够授予对受保护资源的访问权限的实体,指拥有共享数据的人或应用。
  • 第三方应用(也称为客户端client):代表请求受保护的资源的应用程序。
  • 授权服务器:服务器成功后向客户端发出访问令牌,验证资源所有者并获得授权。
  • 资源服务器:托管受保护资源的服务器,能够接受并使用访问令牌响应受保护的资源请求。

    1. ![](https://cdn.nlark.com/yuque/0/2019/png/129208/1575284079021-0891ecd0-0afb-428b-89a1-cd05c71f10ca.png#align=left&display=inline&height=217&originHeight=307&originWidth=431&size=0&status=done&style=none&width=305)

协议流程

  1. ![oauth2.0.png](https://cdn.nlark.com/yuque/0/2019/png/129208/1575284405607-98831857-45c6-4a27-986f-24c63f216faa.png#align=left&display=inline&height=251&name=oauth2.0.png&originHeight=337&originWidth=461&size=9866&status=done&style=none&width=343)

具体步骤如下:
A. 客户端从资源所有者处请求授权
B. 资源所有者返回授权许可给客户端
C. 客户端通过授权许可向授权服务器认证
D. 授权服务器验证客户端身份移机授权许可,返回访问令牌Access Token给客户端
E. 客户端通过访问令牌Access Token访问资源服务器资源
F. 资源服务器验证访问令牌Access Token,有效则返回给客户端受保护的资源

四种授权方式

  • 授权码
  • 隐式许可
  • 资源所有者密码凭据
  • 客户端凭据

以上几种授权方式的详细介绍可以参考OAuth 2.0 的四种方式

例子

微信公众平台开发
腾讯开放平台
github developer

参考

https://apereo.github.io/cas/4.2.x/planning/Architecture.html
https://www.cnblogs.com/ywlaker/p/6113927.html
https://yq.aliyun.com/articles/636281
https://www.zhihu.com/topic/19730683/hot
https://www.zhihu.com/question/342103776/answer/853769078
https://github.com/jeansfish/RFC6749.zh-cn/blob/master/SUMMARY.md