【SSO单点登录】JWT续签问题

【SSO单点登录】JWT续签问题 && OAuth2.0 中的refreshToken刷新机制

本篇速览

  • JWT续签问题
    • 快过期时返回新的token

    • refreshToken

      • 如何判断refreshToken的有效性

      • 扩展 -- OAuth2.0 中的refreshToken刷新机制

    • 其他需要刷新token的情况

      • 用户修改了角色权限
      • 删除了某个身份角色

为什么需要续签

如果给JWT设定了一个有效时间的话,时间到JWT是会过期的。但假如这个时候用户正在提交重要信息,填了一大堆信息,按下按钮时,后台拦截器发现token过期,告知前端,前端直接退回登录页,那这次提交就相当于无效了,还得登录后重新填一遍【当然前端也能做缓存,这里就不考虑那么多了,只是个栗子】

而原始JWT设计下,是没有考虑续签问题的。所以续签(即延长JWT的过期时间)工作需要我们自己来做。

快过期了返回新的token

类似于 Session 认证中的做法: 假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,如果发现 token 的有效期马上快过期了, 服务端就重新生成 token 给客户端。

客户端每次请求都检查新旧token,如果不一致,则更新客户端存储的token。

  • 这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。

refreshToken刷新机制

流程图


用户登录返回两个 token :第一个是 acessToken ,它的过期时间比较短,比如是1天;另外一个是 refreshToken 它的过期时间更长一点,可以是accessToken的2倍:2天。

客户端登录后,将 accessToken和refreshToken 保存在客户端本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,

如果过期的话,就将 refreshToken 传给服务端。如果 refreshToken 有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。

🎆如何判断refreshToken的有效性

将生成的 Refresh Token 以及过期时间存储在服务端的数据库中,由于 Refresh Token 不会在客户端请求业务接口时验证,只有在申请新的 Access Token 时才会验证,所以将 Refresh Token 存储在数据库中,不会对业务接口的响应时间造成影响,也不需要像 Session 一样一直保持在内存中以应对大量的请求。

当然,更安全的方式是,客户端需要绑定一个client_id和secret,服务端会验证这个refreshToken是否是改客户端发起的,防止被盗用【这个是后话了,我们后续基于token的SSO单点登录,验证令牌ticket的时候还会着重讲解】

缺点

  • 重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,提前去通过 refreshToken 获取新的accessToken)。

扩展 -- OAuth2.0中的刷新机制

客户端在获得access token的同时也会在响应信息中得到一个名为expires_in的数据,它表示当前获得的access token会在多少秒以后过期。 当超过该指定的秒数后,access token便会过期。当access token过期后,如果客户端依然用它访问服务,服务端就会返回invalid_token的错误或401错误码。

HTTP/1.1 401 Unauthorized
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{ "error": "invaild_token" }

如果用户访问的时候,客户端的"访问令牌AccessToken"已经过期,则需要使用"更新令牌refreshToken"申请一个新的访问令牌。

客户端发出更新令牌的HTTP请求,包含以下参数:

  • granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。
  • refresh_token:表示早前收到的更新令牌,必选项。
  • scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。
POST /v1/oauth2/token HTTP/1.1
Host: melo.com
Authorization: Bearer zskldjflsdjflksjdflkjsd
Content-Type: application/x-www-form-urlencoded

grent_type=refresh_token&refresh_tokne=ajsldkjflskdfjldfg

其他需要刷新token的情况

用户修改了角色的权限

由于权限是在登录的时候,绑定在token里边了,若登录后,管理员修改了角色的权限,而服务端此时还拿一开始登录的token去获取权限的话,就会出现不同步,所以需要主动刷新token更新权限

删除了某个身份角色

情况跟上边是类似的,本质上也是身份权限发生了变更,只要是token中的信息,发生了变化,而我们之后还要用到,会出现数据不一致的情况,就需要刷新token

#程序员##Java#
全部评论
学到了,感谢分享啊
点赞 回复 分享
发布于 2022-10-14 16:58 山西

相关推荐

05-23 17:41
已编辑
西南交通大学 Java
面得最久的一次,一共一个半小时,java基础,jvm,集合,spring,mybatis,数据库,Linux,计网都有涉及下面是手撕题一开始是这道题/*重构字符串给定一个字符串 s ,检查是否能重新排布其中的字母,使得两相邻的字符不同。返回 s 的任意可能的重新排列。若不可行,返回空字符串 "" 。示例 1:输入: s = "aab"输出: "aba"示例 2:输入: s = "aaab"输出: "" 提示:1 <= s.length <= 500s 只包含小写字母*/感觉短时间内写不出来,然后问面试官能不能换题,面试官换了一题之后才写出来的下面是换过的题/*公共字符按ASCII码升序输出所有符合要求的字符; 如果没有符合要求的字符,则输出空列表[]。样例1输入:2 ["aabbccFFFFx2x2", "aaccddFFFFx2x2", "aabcdFFFFx2x2"]输出:["2", "F", "a", "x"]解释:字符 a 在三个字符串中都出现 2次,符合要求;字符 b 在第二三个字符串中分别出现 0次、1次,不符合要求;字符 c 在第三个字符串中出现 1次,不符合要求;字符 d 在第三个字符串中出现 1次,不符合要求;字符 F 在三个字符串中都出现了 4 次,符合要求;字符 x 在三个字符串中都出现了 2 次,符合要求;字符 2 在三个字符串中都出现了 2 次,符合要求;因此字符 a、F、x、2符合要求,按ASCII码升序输出 */代码实现public class Test {    static char[] commonChars(int count, List<String> strings) {        int[][] counts = new int[strings.size()][128];        //记录每个字符出现的次数        for(int i = 0; i < strings.size(); i++) {            String tmp = strings.get(i);            char[] charArray = tmp.toCharArray();            //记录当前字符串所有字符出现的次数            for(int j = 0; j < charArray.length; j++) {                counts[i][charArray[j]]++;            }        }        //定义变量记录符合条件的字符个数        int resCount = 0;        List<Character> res = new ArrayList<>();        for(int j = 0; j < 128; j++) {            //判断当前字符是否符合次数要求            boolean state = true;            for(int i = 0; i < strings.size();i++) {                if(counts[i][j] < count) {                    state = false;                    break;                }            }            if(state) {                resCount++;                res.add((char)(j));            }        }        char[] resArr = new char[resCount];        for(int i = 0; i < resCount; i++) {            resArr[i] = res.get(i);        }        return resArr;    }    public static void main(String[] args) {        int k = 2;        List<String> strings = new ArrayList<>();        strings.add("aabbccFFFFx2x2");        strings.add("aaccddFFFFx2x2");        strings.add("aabcdFFFFx2x2");        char[] res = commonChars(k, strings);        Arrays.sort(res);        for(char c:res) {            System.out.print(c + " ");        }    }}
华为一面188人在聊 查看2道真题和解析
点赞 评论 收藏
分享
05-22 21:48
已编辑
北京理工大学 C++
5.22上午一面技术面:1h1.为什么需要序列化和反序列化2.protobuf为什么性能高3.怎么通信的,怎么处理的发出和收到的数据4.i++是原子操作吗,为什么不是5.i++的过程是什么,从内存拿出到哪里6.多线程是怎么控制并发冲突的(锁、条件变量、信号量、原子操作)7.条件变量用于什么情况,锁用于什么情况8.这些都是阻塞的,有没有不阻塞的方法9.项目代码量有多少10.tcp三次握手和四次挥手11.tcp如果没有第三次ack会怎样12.如果第三次ack没送到就继续发送了会怎样手撕代码:n个数,计算a+b需要a+b时间,求最少计算时间1.介绍思路 2.指出代码格式不规范的地方 3.有没有做过软件测试?怎么测试的反问下午二面主管面:30min1.最困难的事,还有呢?还有呢?(一直觉得不困难。。)2.为什么要造轮子,不是已经有了吗(主管觉得这个项目没意义。)3.这个项目是哪里找来的(github。。)4.这也能叫项目吗,你为什么叫它项目(。。)5.本科学过哪些课程(开始balabala,被催讲快点别废话)6.学过计算机网络吗?(没有,但是balabala,被催别废话)7.未来的工作规划(balabala)8.秋招选工作看中的点,现实点(说成长,被说不现实。。)9.为什么想来华为(balabala。。)有什么想问的:1.业务和技术栈2.实习的话要提升什么方面(答:那都是虚的,啥也不用提升,来实习了再学就行)3.您觉得对于毕业生找工作哪些方面比较重要(户口,最现实的)。。。鼠鼠主管面完表示很自闭,但是面完秒通过了,主管说他只是一环,具体要排序优中选优。。
yoyoyo选手:感觉主管面很像……是不是他全程不耐烦……戴眼镜
查看27道真题和解析
点赞 评论 收藏
分享
评论
点赞
18
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务