天天看点

使用jwt完成sso单点登录

JWT

在了解jwt之前,先了解一下常用的会话管理

  • 基于

    server-session

    的管理方式
  • cookie-based

    的管理方式
  • token-based

    的管理方式

一.基于

server-session

的管理

  1. 服务端

    session

    是用户第一次访问应用时,服务器就会创建的对象,代表用户的一次会话过程,服务器为每一个

    session

    都分配一个唯一的

    sessionid

    ,以保证每个用户都有一个不同的

    session

    对象。
  2. 服务器在创建完

    session

    后,会把

    sessionid

    通过

    cookie

    返回给用户所在的浏览器,这样当用户第二次及以后向服务器发送请求的时候,就会通过

    cookie

    sessionid

    传回给服务器,以便服务器能够根据

    sessionid

    找到与该用户对应的

    session

    对象。
  3. session

    通常有失效时间的设定,比如2个小时。当失效时间到,服务器会销毁之前的

    session

    ,并创建新的

    session

    返回给用户。但是只要用户在失效时间内,有发送新的请求给服务器,通常服务器都会把他对应的

    session

    的失效时间根据当前的请求时间再延长2个小时。
  4. session

    在一开始并不具备会话管理的作用。它只有在用户登录认证成功之后,并且往

    session

    对象里面放入了用户登录成功的凭证,才能用来管理会话。管理会话的逻辑也很简单,只要拿到用户的

    session

    对象,看它里面有没有登录成功的凭证,就能判断这个用户是否已经登录。当用户主动退出的时候,会把它的

    session

    对象里的登录凭证清掉。所以在用户登录前或退出后或者

    session

    对象失效时,肯定都是拿不到需要的登录凭证的。

以上过程可简单使用流程图描述如下: 

使用jwt完成sso单点登录

它还有一个比较大的优点就是安全性好,因为在浏览器端与服务器端保持会话状态的媒介始终只是一个

sessionid

串,只要这个串够随机,攻击者就不能轻易冒充他人的

sessionid

进行操作;除非通过CSRF或http劫持的方式,才有可能冒充别人进行操作;即使冒充成功,也必须被冒充的用户

session

里面包含有效的登录凭证才行。但是在真正决定用它管理会话之前,也得根据自己的应用情况考虑以下几个问题:

  1. 这种方式将会话信息存储在web服务器里面,所以在用户同时在线量比较多时,这些会话信息会占据比较多的内存;
  2. 当应用采用集群部署的时候,会遇到多台web服务器之间如何做

    session

    共享的问题。因为

    session

    是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建

    session

    的服务器,这样他就拿不到之前已经放入到

    session

    中的登录凭证之类的信息了;
  3. 多个应用要共享

    session

    时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好

    cookie

    跨域的处理。

针对问题1和问题2,我见过的解决方案是采用

redis

这种中间服务器来管理

session

的增删改查,一来减轻web服务器的负担,二来解决不同web服务器共享

session

的问题。针对问题3,由于服务端的

session

依赖

cookie

来传递

sessionid

,所以在实际项目中,只要解决各个项目里面如何实现

sessionid

cookie

跨域访问即可,这个是可以实现的,就是比较麻烦,前后端有可能都要做处理。

二. 

cookie-based

的管理方式

由于前一种方式会增加服务器的负担和架构的复杂性,所以后来就有人想出直接把用户的登录凭证直接存到客户端的方案,当用户登录成功之后,把登录凭证写到

cookie

里面,并给

cookie

设置有效期,后续请求直接验证存有登录凭证的

cookie

是否存在以及凭证是否有效,即可判断用户的登录状态。使用它来实现会话管理的整体流程如下:

  1. 用户发起登录请求,服务端根据传入的用户密码之类的身份信息,验证用户是否满足登录条件,如果满足,就根据用户信息创建一个登录凭证,这个登录凭证简单来说就是一个对象,最简单的形式可以只包含用户

    id

    ,凭证创建时间和过期时间三个值。
  2. 服务端把上一步创建好的登录凭证,先对它做数字签名,然后再用对称加密算法做加密处理,将签名、加密后的字串,写入

    cookie

    cookie

    的名字必须固定(如

    ticket

    ),因为后面再获取的时候,还得根据这个名字来获取

    cookie

    值。这一步添加数字签名的目的是防止登录凭证里的信息被篡改,因为一旦信息被篡改,那么下一步做签名验证的时候肯定会失败。做加密的目的,是防止

    cookie

    被别人截取的时候,无法轻易读到其中的用户信息。
  3. 用户登录后发起后续请求,服务端根据上一步存登录凭证的

    cookie

    名字,获取到相关的

    cookie

    值。然后先做解密处理,再做数字签名的认证,如果这两步都失败,说明这个登录凭证非法;如果这两步成功,接着就可以拿到原始存入的登录凭证了。然后用这个凭证的过期时间和当前时间做对比,判断凭证是否过期,如果过期,就需要用户再重新登录;如果未过期,则允许请求继续。
使用jwt完成sso单点登录

这种方式最大的优点就是实现了服务端的无状态化,彻底移除了服务端对会话的管理的逻辑,服务端只需要负责创建和验证登录

cookie

即可,无需保持用户的状态信息。对于第一种方式的第二个问题,用户会话信息共享的问题,它也能很好解决:因为如果只是同一个应用做集群部署,由于验证登录凭证的代码都是一样的,所以不管是哪个服务器处理用户请求,总能拿到

cookie

中的登录凭证来进行验证;如果是不同的应用,只要每个应用都包含相同的登录逻辑,那么他们也是能轻易实现会话共享的,不过这种情况下,登录逻辑里面数字签名以及加密解密要用到的密钥文件或者密钥串,需要在不同的应用里面共享,总而言之,就是需要算法完全保持一致。

这种方式由于把登录凭证直接存放客户端,并且需要

cookie

传来传去,所以它的缺点也比较明显:

  1. cookie

    有大小限制,存储不了太多数据,所以要是登录凭证存的消息过多,导致加密签名后的串太长,就会引发别的问题,比如其它业务场景需要

    cookie

    的时候,就有可能没那么多空间可用了;所以用的时候得谨慎,得观察实际的登录

    cookie

    的大小;比如太长,就要考虑是非是数字签名的算法太严格,导致签名后的串太长,那就适当调整签名逻辑;比如如果一开始用4096位的RSA算法做数字签名,可以考虑换成1024、2048位;
  2. 每次传送

    cookie

    ,增加了请求的数量,对访问性能也有影响;
  3. 也有跨域问题,毕竟还是要用

    cookie

前面两种会话管理方式因为都用到

cookie

,不适合用在native app里面:native app不好管理

cookie

,毕竟它不是浏览器。这两种方案都不适合用来做纯api服务的登录认证。要实现api服务的登录认证,就要考虑下面要介绍的第三种会话管理方式。

三.

token-based

的管理方式

这种方式从流程和实现上来说,跟

cookie-based

的方式没有太多区别,只不过

cookie-based

里面写到

cookie

里面的

ticket

在这种方式下称为

token

,这个

token

在返回给客户端之后,后续请求都必须通过url参数或者是http header的形式,主动带上

token

,这样服务端接收到请求之后就能直接从http header或者url里面取到token进行验证:

使用jwt完成sso单点登录

这种方式不通过

cookie

进行

token

的传递,而是每次请求的时候,主动把

token

加到http header里面或者url后面,所以即使在native app里面也能使用它来调用我们通过web发布的api接口。app里面还要做两件事情:

  1. 有效存储

    token

    ,得保证每次调接口的时候都能从同一个位置拿到同一个

    token

  2. 每次调接口的的代码里都得把

    token

    加到header或者接口地址里面。

看起来麻烦,其实也不麻烦,这两件事情,对于app来说,很容易做到,只要对接口调用的模块稍加封装即可。

这种方式同样适用于网页应用,

token

可以存于

localStorage

或者

sessionStorage

里面,然后每发ajax请求的时候,都把

token

拿出来放到ajax请求的header里即可。不过如果是非接口的请求,比如直接通过点击链接请求一个页面这种,是无法自动带上

token

的。所以这种方式也仅限于走纯接口的web应用。

这种方式用在web应用里也有跨域的问题,比如应用如果部署在a.com,api服务部署在b.com,从a.com里面发出ajax请求到b.com,默认情况下是会报跨域错误的,这种问题可以用CORS(跨域资源共享)的方式来快速解决。

这种方式跟

cookie-based

的方式同样都还有的一个问题就是

ticket

或者

token

刷新的问题。有的产品里面,你肯定不希望用户登录后,操作了半个小时,结果

ticket

或者

token

到了过期时间,然后用户又得去重新登录的情况出现。这个时候就得考虑

ticket

token

的自动刷新的问题,简单来说,可以在验证

ticket

token

有效之后,自动把

ticket

token

的失效时间延长,然后把它再返回给客户端;客户端如果检测到服务器有返回新的

ticket

token

,就替换原来的

ticket

token

四. 安全问题

在web应用里面,会话管理的安全性始终是最重要的安全问题,这个对用户的影响极大。

首先从会话管理凭证来说,第一种方式的会话凭证仅仅是一个

sessionid

,所以只要这个

sessionid

足够随机,而不是一个自增的数字id值,那么其它人就不可能轻易地冒充别人的

sessionid

进行操作;第二种方式的凭证

ticket

以及第三种方式的凭证

token

都是一个在服务端做了数字签名,和加密处理的串,所以只要密钥不泄露,别人也无法轻易地拿到这个串中的有效信息并对它进行篡改。总之,这三种会话管理方式的凭证本身是比较安全的。

然后从客户端和服务端的http过程来说,当别人截获到客户端请求中的会话凭证,就能拿这个凭证冒充原用户,做一些非法操作,而服务器也认不出来。这种安全问题,可以简单采用https来解决,虽然可能还有http劫持这种更高程度的威胁存在,但是我们从代码能做的防范,确实也就是这个层次了。

JWT介绍 (https://jwt.io/)

JSON Web Token(JWT)

是一个开放标准(RFC 7519),它定义了一种紧凑和自包含的方式,用于在各方之间作为JSON对象安全地传输信息。作为标准,它没有提供技术实现,但是大部分的语言平台都有按照它规定的内容提供了自己的技术实现,所以实际在用的时候,只要根据自己当前项目的技术平台,到官网上选用合适的实现库即可。

使用

JWT

来传输数据,实际上传输的是一个字符串,这个字符串就是所谓的json web token字符串。所以广义上,

JWT

是一个标准的名称;狭义上,

JWT

指的就是用来传递的那个

token

字符串。这个串有两个特点: 

1. 紧凑:指的是这个串很小,能通过url 参数,http请求提交的数据以及http header的方式来传递; 

2. 自包含:这个串可以包含很多信息,比如用户的id、角色等,别人拿到这个串,就能拿到这些关键的业务信息,从而避免再通过数据库查询等方式才能得到它们。

通常一个

JWT

是长这个样子的:

使用jwt完成sso单点登录

要知道一个

JWT

是怎么产生以及如何用于会话管理,只要弄清楚

JWT

的数据结构以及它签发和验证的过程即可。

一. 

JWT

的数据结构以及签发过程

一个

JWT

实际上是由三个部分组成:

header(头部)

payload(载荷)

signature(签名

)。这三个部分在

JWT

里面分别对应英文句号分隔出来的三个串:

使用jwt完成sso单点登录

先来看

header

部分的结构以及它的生成方法。

header

部分是由下面格式的json结构生成出来:

使用jwt完成sso单点登录

这个json中的

typ

属性,用来标识整个

token

字符串是一个

JWT

字符串;它的

alg

属性,用来说明这个

JWT

签发的时候所使用的签名和摘要算法,常用的值以及对应的算法如下:

使用jwt完成sso单点登录

typ

alg

属性的全称其实是

type

algorithm

,分别是类型跟算法的意思。之所以都用三个字母来表示,也是基于

JWT

最终字串大小的考虑,同时也是跟

JWT

这个名称保持一致,这样就都是三个字符了…

typ

alg

JWT

中标准中规定的属性名称,虽然在签发

JWT

的时候,也可以把这两个名称换掉,但是如果随意更换了这个名称,就有可能在

JWT

验证的时候碰到问题,因为拿到

JWT

的人,默认会根据

typ

alg

去拿

JWT

中的

header

信息,当你改了名称之后,显然别人是拿不到

header

信息的,他又不知道你把这两个名字换成了什么。

JWT

作为标准的意义在于统一各方对同一个事情的处理方式,各个使用方都按它约定好的格式和方法来签发和验证

token

,这样即使运行的平台不一样,也能够保证

token

进行正确的传递。

一般签发

JWT

的时候,

header

对应的json结构只需要

typ

alg

属性就够了。

JWT

header

部分是把前面的json结构,经过Base64Url编码之后生成出来的:

使用jwt完成sso单点登录

(在线base64编码:http://www1.tc711.com/tool/BASE64.htm)

再来看

payload

部分的结构和生成过程。

payload

部分是由下面类似格式的json结构生成出来:

使用jwt完成sso单点登录

payload

的json结构并不像

header

那么简单,

payload

用来承载要传递的数据,它的json结构实际上是对

JWT

要传递的数据的一组声明,这些声明被

JWT

标准称为

claims

,它的一个“属性值对”其实就是一个

claim

,每一个

claim

的都代表特定的含义和作用。比如上面结构中的

sub

代表这个

token

的所有人,存储的是所有人的

ID

name

表示这个所有人的名字;

admin

表示所有人是否管理员的角色。当后面对

JWT

进行验证的时候,这些

claim

都能发挥特定的作用。

根据

JWT

的标准,这些

claims

可以分为以下三种类型: 

1. 

Reserved claims(保留)

,它的含义就像是编程语言的保留字一样,属于

JWT

标准里面规定的一些

claim

JWT

标准里面定好的

claim

有:

iss(Issuser)

:代表这个JWT的签发主体; 

sub(Subject)

:代表这个JWT的主体,即它的所有人; 

aud(Audience)

:代表这个JWT的接收对象; 

exp(Expiration time)

:是一个时间戳,代表这个JWT的过期时间; 

nbf(Not Before)

:是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的; 

iat(Issued at)

:是一个时间戳,代表这个JWT的签发时间; 

jti(JWT ID)

:是JWT的唯一标识。

  1. Public claims

    ,略(不重要)
  2. Private claims

    ,这个指的就是自定义的

    claim

    。比如前面那个结构举例中的

    admin

    name

    都属于自定的

    claim

    。这些

    claim

    JWT

    标准规定的

    claim

    区别在于:

    JWT

    规定的

    claim

    JWT

    的接收方在拿到

    JWT

    之后,都知道怎么对这些标准的

    claim

    进行验证;而

    private claims

    不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行。

按照

JWT

标准的说明:保留的

claims

都是可选的,在生成

payload

不强制用上面的那些

claim

,你可以完全按照自己的想法来定义

payload

的结构,不过这样搞根本没必要:第一是,如果把

JWT

用于认证, 那么

JWT

标准内规定的几个

claim

就足够用了,甚至只需要其中一两个就可以了,假如想往

JWT

里多存一些用户业务信息,比如角色和用户名等,这倒是用自定义的

claim

来添加;第二是,

JWT

标准里面针对它自己规定的

claim

都提供了有详细的验证规则描述,每个实现库都会参照这个描述来提供

JWT

的验证实现,所以如果是自定义的

claim

名称,那么你用到的实现库就不会主动去验证这些

claim

最后也是把这个json结构做base64url编码之后,就能生成

payload

部分的串:

使用jwt完成sso单点登录

(在线base64编码:http://www1.tc711.com/tool/BASE64.htm)

最后看

signature

部分的生成过程。签名是把

header

payload

对应的json结构进行base64url编码之后得到的两个串用英文句点号拼接起来,然后根据

header

里面

alg

指定的签名算法生成出来的。算法不同,签名结果不同,但是不同的算法最终要解决的问题是一样的。以

alg: HS256

为例来说明前面的签名如何来得到。按照前面

alg

可用值的说明,HS256其实包含的是两种算法:HMAC算法和SHA256算法,前者用于生成摘要,后者用于对摘要进行数字签名。这两个算法也可以用HMACSHA256来统称。运用HMACSHA256实现

signature

的算法是:

使用jwt完成sso单点登录

正好找到一个在线工具能够测试这个签名算法的结果,比如我们拿前面的

header

payload

串来测试,并把“secret”这个字符串就当成密钥来测试:

使用jwt完成sso单点登录

(https://1024tools.com/hmac)

最后的结果B其实就是JWT需要的signature。不过对比我在介绍JWT的开始部分给出的JWT的举例:

使用jwt完成sso单点登录

会发现通过在线工具生成的

header

payload

都与这个举例中的对应部分相同,但是通过在线工具生成的

signature

与上面图中

的signature

有细微区别,在于最后是否有“=”字符。这个区别产生的原因在于上图中的

JWT

是通过

JWT

的实现库签发的

JWT

,这些实现库最后编码的时候都用的是base64url编码,而前面那些在线工具都是bas64编码,这两种编码方式不完全相同,导致编码结果有区别。

以上就是一个

JWT

包含的全部内容以及它的签发过程。接下来看看该如何去验证一个

JWT

是否为一个有效的

JWT

二.

JWT

的验证过程

这个部分介绍

JWT

的验证规则,主要包括签名验证和

payload

里面各个标准

claim

的验证逻辑介绍。只有验证成功的

JWT

,才能当做有效的凭证来使用。

先说签名验证。当接收方接收到一个

JWT

的时候,首先要对这个

JWT

的完整性进行验证,这个就是签名认证。它验证的方法其实很简单,只要把

header

做base64url解码,就能知道

JWT

用的什么算法做的签名,然后用这个算法,再次用同样的逻辑对

header

payload

做一次签名,并比较这个签名是否与

JWT

本身包含的第三个部分的串是否完全相同,只要不同,就可以认为这个

JWT

是一个被篡改过的串,自然就属于验证失败了。接收方生成签名的时候必须使用跟

JWT

发送方相同的密钥,意味着要做好密钥的安全传递或共享。

再来看

payload

claim

验证,拿前面标准的

claim

来一一说明:

iss(Issuser)

:如果签发的时候这个

claim

的值是“a.com”,验证的时候如果这个

claim

的值不是“a.com”就属于验证失败; 

sub(Subject)

:如果签发的时候这个

claim

的值是“liuyunzhuge”,验证的时候如果这个

claim

的值不是“liuyunzhuge”就属于验证失败; 

(Audience)

:如果签发的时候这个

claim

的值是“[‘b.com’,’c.com’]”,验证的时候这个

claim

的值至少要包含b.com,c.com的其中一个才能验证通过; 

exp(Expiration time)

:如果验证的时候超过了这个

claim

指定的时间,就属于验证失败; 

nbf(Not Before)

:如果验证的时候小于这个

claim

指定的时间,就属于验证失败; 

iat(Issued at)

:它可以用来做一些maxAge之类的验证,假如验证时间与这个

claim

指定的时间相差的时间大于通过maxAge指定的一个值,就属于验证失败; 

jti(JWT ID)

:如果签发的时候这个

claim

的值是“1”,验证的时候如果这个

claim

的值不是“1”就属于验证失败; 

需要注意的是,在验证一个

JWT

的时候,签名认证是每个实现库都会自动做的,但是

payload

的认证是由使用者来决定的。因为

JWT

里面可能不会包含任何一个标准的

claim

,所以它不会自动去验证这些

claim

以登录认证来说,在签发

JWT

的时候,完全可以只用

sub

exp

两个

claim

,用

sub

存储用户的

id

,用

exp

存储它本次登录之后的过期时间,然后在验证的时候仅验证

exp

这个

claim

,以实现会话的有效期管理。

JWT SSO

场景一:用户发起对业务系统的第一次访问,假设他第一次访问的是系统A的some/page这个页面,它最终成功访问到这个页面的过程是:

使用jwt完成sso单点登录

在这个过程里面,我认为理解的关键点在于:

  1. 它用到了两个

    cookie

    (

    jwt

    sid

    )和三次重定向来完成会话的创建和会话的传递;
  2. jwt

    cookie

    是写在systemA.com这个域下的,所以每次重定向到systemA.com的时候,

    jwt

    这个

    cookie

    只要有就会带过去;
  3. sid

    cookie

    是写在cas.com这个域下的,所以每次重定向到cas.com的时候,

    sid

    这个

    cookie

    只要有就会带过去;
  4. 在验证

    jwt

    的时候,如何知道当前用户已经创建了sso的会话? 

    因为

    jwt

    payload

    里面存储了之前创建的sso会话的

    sessionid

    ,所以当cas拿到

    jwt

    ,就相当于拿到了

    sessionid

    ,然后用这个

    sessionid

    去判断有没有的对应的

    session

    对象即可。

还要注意的是:CAS服务里面的

session

属于服务端创建的对象,所以要考虑

sessionid

唯一性以及

session

共享(假如CAS采用集群部署的话)的问题。

sessionid

的唯一性可以通过用户名密码加随机数然后用hash算法如md5简单处理;

session

共享,可以用

memcached

或者

redis

这种专门的支持集群部署的缓存服务器管理

session

来处理。

由于服务端

session

具有生命周期的特点,到期需自动销毁,所以不要自己去写

session

的管理,免得引发其它问题,到github里找开源的缓存管理中间件来处理即可。存储

session

对象的时候,只要用

sessionid

作为key,

session

对象本身作为

value

,存入缓存即可。

session

对象里面除了

sessionid

,还可以存放登录之后获取的用户信息等业务数据,方便业务系统调用的时候,从

session

里面返回会话数据。

场景二:用户登录之后,继续访问系统A的其它页面,如some/page2,它的处理过程是:

使用jwt完成sso单点登录

从这一步可以看出,即使登录之后,也要每次跟CAS校验

jwt

的有效性以及会话的有效性,其实

jwt

的有效性也可以放在业务系统里面处理的,但是会话的有效性就必须到CAS那边才能完成了。当CAS拿到

jwt

里面的

sessionid

之后,就能到

session

缓存服务器里面去验证该

sessionid

对应的

session

对象是否存在,不存在,就说明会话已经销毁了(退出)。

场景三:用户登录了系统A之后,再去访问其他系统如系统B的资源,比如系统B的some/page,它最终能访问到系统B的some/page的流程是:

使用jwt完成sso单点登录

这个过程的关键在于第一次重定向的时候,它会把

sid

这个

cookie

带回给CAS服务器,所以CAS服务器能够判断出会话是否已经建立,如果已经建立就跳过登录页的逻辑。

场景四:用户继续访问系统B的其它资源,如系统B的some/page2:

使用jwt完成sso单点登录

这个场景的逻辑跟场景二完全一致。

场景五:退出登录,假如它从系统B发起退出,最终的流程是:

使用jwt完成sso单点登录

最重要的是要清除

sid

cookie

jwt

cookie

可能业务系统都有创建,所以不可能在退出的时候还挨个去清除那些系统的

cookie

,只要

sid

一清除,那么即使那些

jwt

cookie

在下次访问的时候还会被传递到业务系统的服务端,由于

jwt

里面的

sid

已经无效,所以最后还是会被重定向到CAS登录页进行处理。

方案总结 

以上方案两个关键的前提:

  1. 整个会话管理其实还是基于服务端的

    session

    来做的,只不过这个

    session

    只存在于CAS服务里面;
  2. CAS之所以信任业务系统的

    jwt

    ,是因为这个

    jwt

    是CAS签发的,理论上只要认证通过,就可以认为这个

    jwt

    是合法的。

jwt

本身是不可伪造,不可篡改的,但是不代表非法用户冒充正常用法发起请求,所以常规的几个安全策略在实际项目中都应该使用:

  1. 使用https
  2. 使用http-only的

    cookie

    ,针对

    sid

    jwt

  3. 管理好密钥
  4. 防范CSRF攻击。

尤其是CSRF攻击形式,很多都是钻代码的漏洞发生的,所以一旦出现CSRF漏洞,并且被人利用,那么别人就能用获得的

jwt

,冒充正常用户访问所有业务系统,这个安全问题的后果还是很严重的。考虑到这一点,为了在即使有漏洞的情况将损害减至最小,可以在

jwt

里面加入一个系统标识,添加一个验证,只有传过来的

jwt

内的系统标识与发起

jwt

验证请求的服务一致的情况下,才允许验证通过。这样的话,一个非法用户拿到某个系统的

jwt

,就不能用来访问其它业务系统了。

在业务系统跟CAS发起attach/validate请求的时候,也可以在CAS端做些处理,因为这个请求,在一次SSO过程中,一个系统只应该发一次,所以只要之前已经给这个系统签发过jwt了,那么后续 同一系统的attach/validate请求都可以忽略掉。

总的来说,这个方案的好处有:

  1. 完全分布式,跨平台,CAS以及业务系统均可采用不同的语言来开发;
  2. 业务系统如系统A和系统B,可实现服务端无状态
  3. 假如是自己来实现,那么可以轻易的在CAS里面集成用户注册服务以及第三方登录服务,如微信登录等。

它的缺陷是:

  1. 第一次登录某个系统,需要三次重定向;
  2. 登录后的后续请求,每次都需要跟CAS进行会话验证,所以CAS的性能负载会比较大
  3. 登陆后的后续请求,每次都跟CAS交互,也会增加请求响应时间,影响用户体验。

转载自: 

3种web会话管理的方式 

看图理解JWT如何用于单点登录

参考文献:

https://blog.csdn.net/qq_38401919/article/details/80535258

继续阅读