JWT+cookie单点登录 ゝ一纸荒年。 2023-10-15 14:32 67阅读 0赞 ### 1、什么是JWT ### Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。 通俗来讲,JWT是一个含签名并携带用户相关信息的加密串,页面请求校验登录接口时,请求头中携带JWT串到后端服务,后端通过签名加密串匹配校验,保证信息未被篡改。校验通过则认为是可靠的请求,将正常返回数据。 **JWT适用场景** **授权**: 这是最常见的使用场景,解决单点登录问题。因为JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),所以使用比较广泛; **信息交换**: JWT是在各个服务之间安全传输信息的好方法。因为JWT可以签名,例如,使用公钥/私钥对儿 - 可以确定请求方是合法的。此外,由于使用标头和有效负载计算签名,还可以验证内容是否未被篡改。 ### 2、JWT的数据结构 ### #### 2.1、传统session认证及其弊病 #### 互联网服务离不开用户认证,一般流程如下。 1、用户向服务器发送用户名和密码。 2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。 3、服务器向用户返回一个 session_id,写入用户的 Cookie。 4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。 5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。 如2-1: ![82df9f946a4e4dd88794ed04cbf4106a.png][] 图2-1 一般Session认证流程 这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。 举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现? 一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。 另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。 #### 2.2、JWT原理 #### JWT原理是,服务器认证以后,生成一个JSON对象,发回给用户,如下 { "姓名": "张三", "角色": "管理员", "到期时间": "2023年9月1日0点0分" } 以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。 服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。 #### 2.3、JWT-数据结构 #### 实际JWT如下: ![format_png][] 它是一个很长的字符串,中间用点(`.`)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。 JWT的三个部分依次如下。 > \* Header(头部) > > \* PayLoad(负载) > > \* Signature(签名) 写成一行,就是下面的样子。 Header.Payload.Signature ![format_png 1][] 下面依次介绍这三个部分。 ##### 2.3.1、Header ##### Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子 { "alg": "HS256", "typ": "JWT" } 上面代码中,`alg`属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);`typ`属性表示这个令牌(token)的类型(type),JWT 令牌统一写为`JWT`。 最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。 ##### 2.3.2、Payload ##### Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用。 > \* iss(issuer):签发人 > > \* exp(expiration time):过期时间 > > \* sub(subject):主题 > > \* aud(audience):受众 > > \* nbf(Not Before):生效时间 > > \* iat(Issued At):签发时间 > > \* jti(JWT ID):编号 除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。 { "sub": "1234567890", "name": "John Doe", "admin": true } 注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。 这个 JSON 对象也要使用 Base64URL 算法转成字符串。 ##### 2.3.3、Signature ##### Signature部分是对前两部分的签名,防止数据篡改。 首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。 HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(`.`)分隔,就可以返回给用户。 ##### 2.3.4、Base64URL ##### 前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。 JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符`+`、`/`和`=`,在 URL 里面有特殊含义,所以要被替换掉:`=`被省略、`+`替换成`-`,`/`替换成`_` 。这就是 Base64URL 算法。 客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息`Authorization`字段里面。 Authorization: Bearer <token> 另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。 #### 2.3、JWT认证流程 #### 常规JWT认证流程如下: **第一个为Session认证,第二个为JWT认证,方便比较差异** **![ce6be070bbd246b39447963aeaf2d27d.png][]** 相比于session认证,JWT省去了服务器存储用户信息的过程。 ##### **JWT常规校验流程** ##### ![04f68be5d86c4d3ca5c8e945fe86a8d7.png][] JWT常见校验流程 其中设置 payload 校验规则一般是检查 nbf、exp 以及用户自定义的一些字段。 #### 2.4、使用JWT实现单点登录(完全跨域方案) #### 基于 cookie 的单点登录模式有一个弊病在于,其对应的多个站点的顶级域名必须相同。 ![ea2a74501ebe4291ae45d8b1a9f8ce99.png][] ![9190fea1d0c04bd08c69dcb8586448fa.png][] **主要有以下三步:** 项目一开始先封装了一个JWTHelper工具包(GitHub下载),主要提供了生成JWT、解析JWT以及校验JWT的方法,其它还有一些加密相关操作。 接下来,我在客户端项目中依赖JWTHelper工具包,并添加Interceptor拦截器,拦截需要校验登录的接口。拦截器中校验JWT有效性,并在response中重新设置JWT的新值; 最后在JWT服务端,依赖JWT工具包,在登录方法中,需要在登录校验成功后调用生成JWT方法,生成一个JWT令牌并且设置到response的header中。 *参考 使用JWT实现单点登录(完全跨域方案)[https://blog.csdn.net/weixin\_42873937/article/details/82460997][https_blog.csdn.net_weixin_42873937_article_details_82460997]* #### 2.5、access\_token和refresh\_token #### refresh\_token和access\_token都是OAuth 2.0授权机制中的重要概念。 access\_token是一个用于访问受保护资源的令牌。例如,当用户登录到某个应用程序时,应用程序可以获得一个access\_token,以便在不需要用户重新登录的情况下访问用户数据。access\_token通常有一个过期时间,在过期之前,应用程序可以使用该令牌来访问受保护的资源。 refresh\_token是一个用于刷新access\_token的令牌。当access\_token过期后,应用程序可以使用refresh\_token来获取新的access\_token。refresh\_token通常比access\_token的过期时间更长,并且只有在用户注销或撤销授权之后才会失效。 综上所述,access\_token用于访问受保护的资源,而refresh\_token用于获取新的access\_token。通过使用两者,应用程序可以在不需要用户再次输入凭证的情况下保持对用户数据的持续访问。 > 通常在使用JWT的时候会设置access\_token和refresh\_token两个token,access\_token有效期较短,refresh\_token有效期较长,当access\_token过期之后,如果refresh\_token没有过期则可以换取新的access\_token。我的疑问在于为什么不直接给access\_token设置一个较长的有效期。如果是为了安全,能拿到access\_token,拿到refresh\_token就是轻而易举的事;还有的说法是refresh\_token中可以存放比access\_token更多、验证起来更复杂的信息。 > > Token作为用户获取受保护资源的凭证,必须设置一个过期时间,否则一次登录便可永久使用,认证功能就失去了意义。但是矛盾在于:过期时间设置得太长,用户数据的安全性将大打折扣;过期时间设置得太短,用户就必须每隔一段时间重新登录,以获取新的凭证,这会极大挫伤用户的积极性。针对这一问题,我们可以利用Access / Refresh Token这一概念来平衡Token安全性和用户体验。 Access/Refresh Token是什么? ![a3101453b2f645d7aa67ab6512600084.png][] 上图表示Access/Refresh Token在客户端、认证服务器、资源服务器三者之间的传递关系,简单来说: * **Access Token即“访问令牌”,是客户端向资源服务器换取资源的凭证;** * **Refresh Token即“刷新令牌”,是客户端向认证服务器换取Access Token的凭证。** **Access/Refresh Token如何使用?** ![a9a8ea9e79944f52aace620d0120c46d.png][] 上图表示客户端请求资源的过程中,Access Token 和 Refresh Token 是如何配合使用的: 1. 用户提供身份信息(一般是\[用户名/密码\],利用客户端向认证服务器换取 Refresh Token和Access Token); 2. 客户端携带Access Token访问资源服务器,资源服务器识别Access Token并返回资源; 3. 当Access Token过期或失效,客户端再一次访问资源服务器,**资源服务器返回“无效token”报错**; 4. 客户端通过**Refresh Token向认证服务器换取Access Token**,认证服务器返回**新的**Access Token。 ## 3. 参考 ## (1)10分钟了解JSON Web令牌(JWT) [https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=pc][https_baijiahao.baidu.com_s_id_1608021814182894637_wfr_spider_for_pc] (2)JWT的使用流程 [https://blog.csdn.net/shmely/article/details/85915044][https_blog.csdn.net_shmely_article_details_85915044] (3)JWT全面解读、使用步骤 [https://blog.csdn.net/achenyuan/article/details/80829401][https_blog.csdn.net_achenyuan_article_details_80829401] (4)JSON Web Token 入门教程 -阮一峰 [http://www.ruanyifeng.com/blog/2018/07/json\_web\_token-tutorial.html][http_www.ruanyifeng.com_blog_2018_07_json_web_token-tutorial.html] 【说明】jwt结构讲得比较清晰。 (5)JWT(JSON Web Tokens) [https://www.cnblogs.com/zaixiuxing/p/6005968.html][https_www.cnblogs.com_zaixiuxing_p_6005968.html] (6)使用JWT实现单点登录(完全跨域方案) [https://blog.csdn.net/weixin\_42873937/article/details/82460997][https_blog.csdn.net_weixin_42873937_article_details_82460997] (7)基于 JWT 的单点登录设计 [基于 JWT 的单点登录设计 - 简书][JWT _ -] 【说明】有逻辑图,介绍得清晰。 (8)JWT全面解读、使用步骤 [https://blog.csdn.net/achenyuan/article/details/80829401][https_blog.csdn.net_achenyuan_article_details_80829401] 【说明】JAVA实现代码 (9)看图理解JWT如何用于单点登录 [https://www.shuzhiduo.com/A/kPzORnodxn/][https_www.shuzhiduo.com_A_kPzORnodxn] [82df9f946a4e4dd88794ed04cbf4106a.png]: https://img-blog.csdnimg.cn/82df9f946a4e4dd88794ed04cbf4106a.png [format_png]: https://img-blog.csdnimg.cn/img_convert/6c673591c0985e3c3db5f0806b0e1acd.webp?x-oss-process=image/format,png [format_png 1]: https://img-blog.csdnimg.cn/img_convert/fee45e32d068c93333c8942d427c1991.webp?x-oss-process=image/format,png [ce6be070bbd246b39447963aeaf2d27d.png]: https://img-blog.csdnimg.cn/ce6be070bbd246b39447963aeaf2d27d.png [04f68be5d86c4d3ca5c8e945fe86a8d7.png]: https://img-blog.csdnimg.cn/04f68be5d86c4d3ca5c8e945fe86a8d7.png [ea2a74501ebe4291ae45d8b1a9f8ce99.png]: https://img-blog.csdnimg.cn/ea2a74501ebe4291ae45d8b1a9f8ce99.png [9190fea1d0c04bd08c69dcb8586448fa.png]: https://img-blog.csdnimg.cn/9190fea1d0c04bd08c69dcb8586448fa.png [https_blog.csdn.net_weixin_42873937_article_details_82460997]: https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fweixin_42873937%2Farticle%2Fdetails%2F82460997 [a3101453b2f645d7aa67ab6512600084.png]: https://img-blog.csdnimg.cn/a3101453b2f645d7aa67ab6512600084.png [a9a8ea9e79944f52aace620d0120c46d.png]: https://img-blog.csdnimg.cn/a9a8ea9e79944f52aace620d0120c46d.png [https_baijiahao.baidu.com_s_id_1608021814182894637_wfr_spider_for_pc]: https://links.jianshu.com/go?to=https%3A%2F%2Fbaijiahao.baidu.com%2Fs%3Fid%3D1608021814182894637%26wfr%3Dspider%26for%3Dpc [https_blog.csdn.net_shmely_article_details_85915044]: https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fshmely%2Farticle%2Fdetails%2F85915044 [https_blog.csdn.net_achenyuan_article_details_80829401]: https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fachenyuan%2Farticle%2Fdetails%2F80829401 [http_www.ruanyifeng.com_blog_2018_07_json_web_token-tutorial.html]: https://links.jianshu.com/go?to=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2018%2F07%2Fjson_web_token-tutorial.html [https_www.cnblogs.com_zaixiuxing_p_6005968.html]: https://links.jianshu.com/go?to=https%3A%2F%2Fwww.cnblogs.com%2Fzaixiuxing%2Fp%2F6005968.html [JWT _ -]: https://www.jianshu.com/p/6c4e1804653f [https_www.shuzhiduo.com_A_kPzORnodxn]: https://links.jianshu.com/go?to=https%3A%2F%2Fwww.shuzhiduo.com%2FA%2FkPzORnodxn%2F
相关 单点登录 Shiro 1.2 开始提供了 Jasig CAS 单点登录的支持,单点登录主要用于多系统集成,即在多个 系统中,用户只需要到一个中央服务器登录一次即可访问 比眉伴天荒/ 2023年07月08日 14:25/ 0 赞/ 21 阅读
相关 单点登录 官网 https://apereo.github.io/cas/4.2.x/planning/Architecture.html demo http://www.i 我不是女神ヾ/ 2022年11月03日 10:45/ 0 赞/ 233 阅读
相关 单点登录 业务需要,正在研究. 基本有以下三种方案 1.集中管理Session. 实现很简单,但缺点是 每次页面刷新都需要访问一次或两次 Session管理服务器, 水深无声/ 2022年09月19日 10:55/ 0 赞/ 236 阅读
相关 单点登录 1:什么事单点登录: SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主 男娘i/ 2022年07月13日 14:29/ 0 赞/ 227 阅读
相关 单点登录 一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务 港控/mmm°/ 2022年06月11日 00:55/ 0 赞/ 240 阅读
相关 单点登录 项目分为三个模块 server client2 client1 server提供的接口 /user /tol 深藏阁楼爱情的钟/ 2022年05月24日 04:26/ 0 赞/ 274 阅读
相关 单点登录 1.3 CAS服务端部署 Cas服务端其实就是一个war包。 在资源\\cas\\source\\cas-server-4.0.0-release\\cas-serve 梦里梦外;/ 2022年05月16日 08:04/ 0 赞/ 297 阅读
相关 单点登录 初识单点登录 最初接触到单点登录要追溯到3年多以前了,那时候看到的只是passport,当时要做全国所有社区的登录,然后就照着内部文档写了代码,然后就接入了(这里要提一句 谁借莪1个温暖的怀抱¢/ 2022年05月13日 14:04/ 0 赞/ 272 阅读
相关 单点登录 以Cookie作为凭证媒介 最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。 用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用 £神魔★判官ぃ/ 2022年04月23日 13:18/ 0 赞/ 312 阅读
相关 单点登录 什么是单点登录? 单点登录(Single Sign On)说的简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其它系统中登录。也就是用户的一次登录能得到其它所有 布满荆棘的人生/ 2021年11月11日 04:10/ 0 赞/ 455 阅读
还没有评论,来说两句吧...