jwt的token自动续约_JWT的TOKEN续期功能

2023-11-19

JWT里有一个关键的东东,就是续期TOKEN,即TOKEN快过期时,刷新一个新的TOKEN给客户端.

办法如下:

1.后端生成TOKEN

import com.starmark.core.shiro.model.SecurityUser;

import com.starmark.core.shiro.model.UserLoginToken;

import com.starmark.core.shiro.util.JWTUtil;

import org.apache.commons.lang3.BooleanUtils;

import org.apache.commons.lang3.StringUtils;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.web.filter.authc.AuthenticatingFilter;

import org.apache.shiro.web.util.WebUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.time.LocalDateTime;

import java.time.ZoneId;

import java.util.Date;

import java.util.Objects;

public class JwtAuthFilter extends AuthenticatingFilter {

private final Logger log = LoggerFactory.getLogger(JwtAuthFilter.class);

//10分钟后刷新token

private static final int tokenRefreshInterval = 60 * 10;

@Override

protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {

HttpServletRequest httpServletRequest = WebUtils.toHttp(request);

if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) //对于OPTION请求做拦截,不做token校验

return false;

return super.preHandle(request, response);

}

@Override

protected void postHandle(ServletRequest request, ServletResponse response) {

request.setAttribute("jwtShiroFilter.FILTERED", true);

}

@Override

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {

if (this.isLoginRequest(request, response)) {

return true;

}

Boolean afterFiltered = (Boolean) (request.getAttribute("jwtShiroFilter.FILTERED"));

if (BooleanUtils.isTrue(afterFiltered))

return true;

boolean allowed = false;

try {

allowed = executeLogin(request, response);

} catch (IllegalStateException e) { //not found any token

log.error("Not found any token");

} catch (Exception e) {

log.error("Error occurs when login", e);

}

return allowed || super.isPermissive(mappedValue);

}

@Override

protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {

String jwtToken = getAuthzHeader(servletRequest);

if (StringUtils.isNotBlank(jwtToken) && !JWTUtil.isTokenExpired(jwtToken))

return UserLoginToken.buildPassword(jwtToken, null, "jwt");

return null;

}

@Override

protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse);

httpResponse.sendRedirect("/unauth");

return false;

}

@Override

protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) {

HttpServletResponse httpResponse = WebUtils.toHttp(response);

if (token instanceof UserLoginToken && "jwt".equalsIgnoreCase(((UserLoginToken) token).getLoginType())) {

UserLoginToken jwtToken = (UserLoginToken) token;

boolean shouldRefresh = shouldTokenRefresh(Objects.requireNonNull(JWTUtil.getIssuedAt(jwtToken.getUsername())));

if (shouldRefresh) {

//生成新的TOKEN

SecurityUser user = (SecurityUser) subject.getPrincipal();

String newToken = JWTUtil.sign(user.getUserInfo().getId());

httpResponse.setHeader("x-auth-token", newToken);

}

}

return true;

}

@Override

protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {

log.error("Validate token fail, token:{}, error:{}", token.toString(), e.getMessage());

return false;

}

/**

* 获取TOKEN

* @param request 请求

* @return token

*/

private String getAuthzHeader(ServletRequest request) {

HttpServletRequest httpRequest = WebUtils.toHttp(request);

String header = httpRequest.getHeader("x-auth-token");

return StringUtils.removeStart(header, "Bearer ");

}

/**

* 判断是否需要刷新TOKEN

* @param issueAt token签发日期

* @return 是否需要刷新TOKEN

*/

private boolean shouldTokenRefresh(Date issueAt) {

LocalDateTime issueTime = LocalDateTime.ofInstant(issueAt.toInstant(), ZoneId.systemDefault());

return LocalDateTime.now().minusSeconds(tokenRefreshInterval).isAfter(issueTime);

}

}

原签发TOKEN后10分钟后刷新新的TOKEN

2.前端获取TOKEN

// 拦截响应response,并做一些错误处理

axios.interceptors.response.use((response) => {

if(response.status ===200 && response.data && response.data.code === 401) {

//console.log(window.location.origin);

window.location.href=window.location.origin+window.location.pathname+'#/login';

}

//获取返回的TOKEN

const token=response.headers['x-auth-token'];

if(token) {

//将续期的TOKEN存起来

localStorage.setItem("token",token) ;

}

// 这里是填写处理信息

return response;

}, (err) => { // 这里是返回状态码不为200时候的错误处理

console.log(err);

if(err && err.response) {

switch(err.response.data.code) {

case 400:

err.message = '请求错误';

break;

case 401:

err.message = '未授权,请登录';

break;

case 403:

err.message = '无权限';

break;

case 404:

err.message = `请求地址出错: ${err.response.config.url}`;

break;

case 408:

err.message = '请求超时';

break;

case 500:

err.message = '服务器内部错误';

break;

case 501:

err.message = '服务未实现';

break;

case 502:

err.message = '网关错误';

break;

case 503:

err.message = '服务不可用';

break;

case 504:

err.message = '网关超时';

break;

case 505:

err.message = 'HTTP版本不受支持';

break;

default:

}

}

Vue.prototype.$message.error(err.response.data.msg!=null?err.response.data.msg:err.message);

return Promise.reject(err)

});

注意一点,需要通过过滤器调整FITLER,增加Access-Control-Expose-Headers的输出,否则无法获取response中的header.

至此,JWT的TOKEN续期功能完成.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jwt的token自动续约_JWT的TOKEN续期功能 的相关文章

  • 常用的偏微分方程

    偏微分方程通常包含两个以上的自变量 若自变量同时间相关 或者无关 称其为发展型 或者稳态 的 下面 我们罗列出一些典型的偏微分方程 如 热传导方程 一阶双曲守恒律方程 二阶波动方程 椭圆型偏微分方程等 抛物型偏微分方程通常刻画 个物理系统的
  • 前端学科面试题大全

    作用域和值类型引用类型的传递 变量作用域 作用域变量访问区域 变量值存在栈中 变量赋值相当于值赋值 值传递与引用传递有哪些区别 函数内部 变量会先声明 形式参数变量声明提升 整个函数体有var声明的变量 如果没有访问全局定义的num2 函数
  • 服务器环境初始化配置

    工程实践经验积累 服务器环境初始化配置 1 新建环境 新建环境 是为了使自己的程序在一个相对独立的环境中运行 不影响服务器上其他用户 并不受其他用户影响 新建环境的语句为 conda create n your env name pytho
  • 【Unity Shader】屏幕后处理1.0:调整亮度/饱和度/对比度

    1 Unity中实现屏幕特效的基本步骤 什么叫屏幕后处理 Screen post processing effects 渲染完整个场景得到屏幕图像后对图像进行一系列操作 实现各种屏幕特效 这一步我们可以添加很多例如景深 Depth of F
  • session销毁

    session invalidate session invalidate的销毁是把这个session所带的用户彻底的销毁 这个session跟用户已经紧密联合在一起 所以就一起销毁了 这样就算换了个session 也是登陆不了的 以前我的
  • 设计模式之享元模式

    享元模式 就是共享技术 对于系统中存在大量相同的对象 把他们抽取成一个对象放在缓存中进行使用 这样可以大大节省系统资源 例如 围棋棋盘上有两种棋子 一个是黑子 一个是白子 如果在下棋的时候每下一个棋子就要new一个棋子对象 那么就会有大量的
  • C#比较两个list集合,两集合同时存在或A集合存在B集合中无

    using System using System Collections Generic using System Linq using System Text using System Threading using System Th
  • iOS灵动岛【电商秒杀】开发实践

    一 基本概述 名词基础知识 苹果在 iPhone 14 Pro 系列中增加一个灵动岛 主要目的是隐藏挖孔造型的高端 感叹号屏 通过动画的视觉差异 用户找不到原来的挖孔屏 灵动岛是一种巧妙的设计 模糊了软件和硬件之间的界限 它可以在锁屏的情况
  • Python: 转换文本编码

    最近在做周报的时候 需要把csv文本中的数据提取出来制作表格后生产图表 在获取csv文本内容的时候 基本上都是用with open filename encoding UTF 8 as f 来打开csv文本 但是实际使用过程中发现有些csv
  • python网络爬虫实战——实时抓取西刺免费代理ip

    参考网上高手示例程序 利用了多线程技术 Python版本为2 7 coding utf8 import urllib2 import re import threading import time rawProxyList checkedP
  • Git切换分支报错:error: you need to resolve your current index first 以及needs merge

    当想从子分支切换到dev分支时git checkout dev 报错 error you need to resolve your current index first xxx java needs merge xxx xml needs
  • c#:ThreadPool实现并行分析,并实现线程同步结束

    背景 一般情况下 经常会遇到一个单线程程序时执行对CPU MEMORY IO利用率上不来 且速度慢下问题 那么 怎么解决这些问题呢 据我个人经验来说有以下两种方式 1 并行 多线程 Parallel Task ThreadPool 2 多进
  • phpstrom、laradock、xdebug 进行断点调试

    phpstrom laradock xdebug 进行断点调试 背景 laravel 框架封装太完善 经常搞不明白究竟用的是哪个类 复杂一点的算法 使用 dd方法调试时 需要疯狂dd 显得过于鸡肋 调试流程 发请求 跑调试代码 安装 xde
  • 决策树之用信息增益选择最优特征

    决策树之用信息增益选择最优特征 熵 熵的定义 熵 sh ng 热力学中表征物质状态的参量之一 用符号S表示 其物理意义是体系混乱程度的度量 在决策树中 信息增益是由熵构建而成 表示的是 随机变量的不确定性 不确定性越大 代表着熵越大 随机变
  • Mycat 学习小结

    Mycat 学习小结 Mycat 是什么 Mycat 是一个彻底开源的面向企业应用开发的大数据库集群 支持事务 ACID 是可以替代Mysql 的加强版数据库 Mycat被视为 Mysql 集群的企业级数据库 用来替代昂贵的 Oracle
  • LuCI界面开发之CBI模块

    在openWrt路由界面的开发中 我们使用的LuCI实际上已经不是简单的html了 它是嵌合于lua语言中的元素 或者按照英文翻译来说不是那些input而是变为如asp net中使用的那些控件 或者是 类 这些类包括一些常用的input输入
  • 编程每日一题_C程序设计_判断是否为素数

    描述 给定整型数据 判断其是否为素数 质数 又称素数 是指在大于1的自然数中 除了1和它本身外 不能被其他自然数整除 除0以外 的数称之为素数 质数 比1大但不是素数的数称为合数 1和0既非素数也非合数 素数 质数 与合数 定义存疑 解法一
  • 分支-11. 计算工资(15)

    某公司员工的工资计算方法如下 一周内工作时间不超过40小时 按正常工作时间计酬 超出40小时的工作时间部分 按正常工作时间报酬的1 5倍计酬 员工按进公司时间分为新职工和老职工 进公司不少于5年的员工为老职工 5年以下的为新职工 新职工的正

随机推荐