使用 jwt 完成 sso 单点登录

原文链接:http://www.bestqliang.com/2018/06/02/%E4%BD%BF%E7%94%A8jwt%E5%AE%8C%E6%88%90sso%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/

JWT

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

  1. 基于 server-session 的管理方式

  2. cookie-based 的管理方式

  3. 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 对象失效时,肯定都是拿不到需要的登录凭证的。

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

它还有一个比较大的优点就是安全性好,因为在浏览器端与服务器端保持会话状态的媒介始终只是一个 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. 服务端把上一步创建好的登录凭证,先对它做 数字签名,然后再用 对称加密算法 做加密处理,将签名、加密后的字串,写入 cookiecookie 的名字必须固定(如ticket),因为后面再获取的时候,还得根据这个名字来获取 cookie 值。这一步添加数字签名的目的是防止登录凭证里的信息被篡改,因为一旦信息被篡改,那么下一步做签名验证的时候肯定会失败。做加密的目的,是防止cookie被别人截取的时候,无法轻易读到其中的用户信息
  3. 用户登录后发起后续请求,服务端根据上一步存登录凭证的 cookie 名字,获取到相关的 cookie 值。然后先做解密处理,再做数字签名的认证,如果这两步都失败,说明这个登录凭证非法;如果这两步成功,接着就可以拿到原始存入的登录凭证了。然后用这个凭证的过期时间和当前时间做对比,判断凭证是否过期,如果过期,就需要用户再重新登录;如果未过期,则允许请求继续。

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

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

对于上面的第一种方式[ server-session]的第二个问题,用户会话信息共享的问题,它也能很好解决:因为如果只是同一个应用做集群部署,由于验证登录凭证的代码都是一样的,所以不管是哪个服务器处理用户请求,总能拿到 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进行验证:

这种方式不通过 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 是怎么产生以及如何用于会话管理,只要弄清楚 JWT 的数据结构以及它签发和验证的过程即可。

 

1,JWT 的数据结构以及签发过程

一个 JWT 实际上是由三个部分组成:header(头部)payload(载荷)和 signature(签名)。这三个部分在 JWT 里面分别对应英文句号分隔出来的三个串:

先来看 header 部分的结构以及它的生成方法。header 部分是由下面格式的json结构生成出来:

这个json中的 typ属性,用来标识整个 token字符串 是一个 JWT字符串;它的 alg属性,用来说明这个 JWT 签发的时候所使用的签名摘要算法,常用的值以及对应的算法如下:

typ 跟 alg 属性的全称其实是 type  algorithm,分别是 类型 算法 的意思。之所以都用三个字母来表示,也是基于 JWT 最终字串大小的考虑,同时也是跟JWT这个名称保持一致,这样就都是三个字符了…

typ 跟 alg 是 JWT中标准中规定的属性名称,虽然在 签发JWT 的时候,也可以把这两个名称换掉,但是如果随意更换了这个名称,就有可能在 JWT验证 的时候碰到问题,因为拿到JWT的人,默认会根据typalg去拿JWT中的header信息,当你改了名称之后,显然别人是拿不到header信息的,他又不知道你把这两个名字换成了什么。【JWT作为标准的意义在于统一各方对同一个事情的处理方式,各个使用方都按它约定好的格式和方法来签发和验证token,这样即使运行的平台不一样,也能够保证 token 进行正确的传递。】

一般 签发JWT 的时候,header 对应的json结构只需要 typalg属性 就够了。JWTheader部分是把前面的json结构,经过Base64Url编码之后生成出来的:

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


 

再来看 payload 部分的结构和生成过程。payload 部分是由下面类似格式的json结构生成出来:

payload 的json结构并不像 header 那么简单,payload 用来承载要传递的数据,它的json结构实际上是对 JWT 要传递的数据的一组声明,这些声明被 JWT 标准称为claims,它的一个 "属性值对" 其实就是一个 claim,每一个 claim 的都代表特定的含义和作用。比如上面结构中的 sub 代表这个 token 的所有人,存储的是所有人的 IDname 表示这个所有人的名字;admin 表示所有人是否管理员的角色。当后面对 JWT 进行验证的时候,这些 claim 都能发挥特定的作用。

根据 JWT 的标准,这些 claims 可以分为以下三种类型: 

  1. Reserved claims(保留),它的含义就像是编程语言的保留字一样,属于JWT标准里面规定的一些claimJWT标准里面定好的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的唯一标识】。
  2. Public claims,略(不重要)
  3. Private claims,这个指的就是 自定义的claim。比如前面那个结构举例中的 adminname 都属于自定的claim。这些claimJWT标准规定的claim区别在于:JWT规定的claimJWT的接收方在拿到JWT之后,都知道怎么对这些标准的claim进行验证;而 private claims 不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行。

按照 JWT标准 的说明:保留的claims都是可选的,在生成payload不强制用上面的那些claim,你可以完全按照自己的想法来定义payload的结构。不过这样搞根本没必要:

  1. 第一是,如果把 JWT用于认证, 那么 JWT标准 内规定的几个 claim 就足够用了,甚至只需要其中一两个就可以了,假如想往 JWT 里多存一些用户业务信息,比如角色和用户名等,这倒是用 自定义的claim 来添加;
  2. 第二是,JWT标准 里面针对它自己规定的claim都提供了有详细的验证规则描述,每个实现库都会参照这个描述来提供JWT的验证实现,所以如果是自定义的claim名称,那么你用到的实现库就不会主动去验证这些claim

最后也是把这个json结构做base64url编码之后,就能生成 payload 部分的串:

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


 

最后看 signature 部分的生成过程。签名是把 headerpayload 对应的 json结构 进行 base64url编码 之后得到的两个串用英文句点号拼接起来,然后根据 header 里面 alg指定的签名算法 生成出来的。算法不同,签名结果不同,但是不同的算法最终要解决的问题是一样的。

以 alg: HS256 为例来说明前面的签名如何来得到:

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

正好找到一个在线工具能够测试这个签名算法的结果,比如我们拿前面的 header  payload 串来测试,并把“secret”这个字符串就当成密钥来测试:

https://1024tools.com/hmac

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

会发现通过在线工具生成的 headerpayload 都与这个举例中的对应部分相同,但是通过在线工具生成的 signature 与上面图中 signature 有细微区别,在于最后是否有“=”字符。

这个区别产生的原因在于上图中的JWT是通过JWT的实现库签发的JWT,这些实现库最后编码的时候都用的是base64url编码,而前面那些在线工具都是bas64编码,这两种编码方式不完全相同,导致编码结果有区别。

以上就是一个 JWT 包含的全部内容以及它的签发过程。接下来看看该如何去验证一个 JWT 是否为一个有效的 JWT

 

2,JWT 的验证过程

 这个部分介绍 JWT的验证规则,主要包括 签名验证 和 payload里面各个标准 claim 的验证逻辑介绍。只有验证成功的JWT,才能当做有效的凭证来使用。

【先说签名验证】

当接收方接收到一个 JWT 的时候,首先要对这个 JWT的完整性 进行验证,这个就是签名认证。它验证的方法其实很简单,只要把 header base64url解码,就能知道JWT用的什么算法做的签名,然后用这个算法,再次用同样的逻辑headerpayload做一次签名,并比较这个签名是否与JWT本身包含的第三个部分的串是否完全相同,只要不同,就可以认为这个JWT是一个被篡改过的串,自然就属于验证失败了。接收方生成签名的时候必须使用跟JWT发送方相同的密钥,意味着要做好密钥的安全传递共享

【再来看 payloadclaim验证,拿前面标准的claim来一一说明: 

  1. iss(Issuser):如果签发的时候这个claim的值是“a.com”,验证的时候如果这个claim的值不是“a.com”就属于验证失败; 
  2. sub(Subject):如果签发的时候这个claim的值是“liuyunzhuge”,验证的时候如果这个claim的值不是“liuyunzhuge”就属于验证失败; 
  3. (Audience):如果签发的时候这个claim的值是“[‘b.com’,’c.com’]”,验证的时候这个claim的值至少要包含b.com,c.com的其中一个才能验证通过; 
  4. exp(Expiration time):如果验证的时候超过了这个claim指定的时间,就属于验证失败; 
  5. nbf(Not Before):如果验证的时候小于这个claim指定的时间,就属于验证失败; 
  6. iat(Issued at):它可以用来做一些maxAge之类的验证,假如验证时间与这个claim指定的时间相差的时间大于通过maxAge指定的一个值,就属于验证失败; 
  7. jti(JWT ID):如果签发的时候这个claim的值是“1”,验证的时候如果这个claim的值不是“1”就属于验证失败; 

需要注意的是:在验证一个JWT的时候,签名认证是每个实现库都会自动做的,但是payload的认证是由使用者来决定的。因为JWT里面可能不会包含任何一个标准的 claim,所以它不会自动去验证这些 claim

以登录认证来说:在签发JWT的时候,完全可以只用 subexp 两个 claim,用sub存储用户的id,用exp存储它本次登录之后的过期时间,然后在验证的时候仅验证exp这个claim,以实现会话的有效期管理。


 

 

JWT SSO

单点登录 SSO(Single Sign On)单点登录是实现多个系统之间统一登录的验证系统,简单来说就是:有A,B,C三个系统,在A处登录过后,再访问B系统,B系统就已经处于了登录状态,C系统也是一样。

举个生活中栗子:你同时打开天猫和淘宝,都进入login界面,都要求你登录的,现在你在淘宝处登录后,直接在天猫处刷新,你会发现,你已经登录了,而且就是你在淘宝上登录的用户。说明他们实现了SSO,并且持有相同的信息。

当然这个特性意味着它的使用场景是:同一公司下的不同子系统,因为对于SSO来说,每一个子系统拥有的信息都一样,是用户的全部信息,如果是不同公司,那这肯定不合适。现在的天猫和淘宝就是这样的一套SSO。


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

 

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

  1. 它用到了两个 cookie(jwtsid) 和三次重定向来完成会话的创建和会话的传递;

  2. jwtcookie 是写在systemA.com这个域下的,所以每次重定向到systemA.com的时候,jwt这个cookie只要有就会带过去;

  3. sidcookie 是写在cas.com这个域下的,所以每次重定向到cas.com的时候,sid这个cookie只要有就会带过去;

  4. 在验证jwt的时候,如何知道当前用户已经创建了sso的会话? 
    因为 jwtpayload 里面存储了之前创建的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,它的处理过程是:

从这一步可以看出,即使登录之后,也要每次跟CAS校验 jwt 的有效性以及会话的有效性,其实jwt的有效性也可以放在业务系统里面处理的,但是会话的有效性就必须到CAS那边才能完成了。当CAS拿到 jwt 里面的 sessionid 之后,就能到 session缓存服务器 里面去验证该 sessionid 对应的 session对象 是否存在,不存在,就说明会话已经销毁了(退出)。

 

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

 这个过程的关键在于第一次重定向的时候,它会把 sid 这个 cookie 带回给CAS服务器,所以CAS服务器能够判断出会话是否已经建立,如果已经建立就跳过登录页的逻辑。

 

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

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

 

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

最重要的是要清除 sidcookiejwt 的 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,针对 sidjwt
  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如何用于单点登录

 

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值