JWT的TOKEN续期功能

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

办法如下:

1.后端生成TOKEN

importcom.starmark.core.shiro.model.SecurityUser;importcom.starmark.core.shiro.model.UserLoginToken;importcom.starmark.core.shiro.util.JWTUtil;importorg.apache.commons.lang3.BooleanUtils;importorg.apache.commons.lang3.StringUtils;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.subject.Subject;importorg.apache.shiro.web.filter.authc.AuthenticatingFilter;importorg.apache.shiro.web.util.WebUtils;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.web.bind.annotation.RequestMethod;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.time.LocalDateTime;importjava.time.ZoneId;importjava.util.Date;importjava.util.Objects;publicclassJwtAuthFilterextendsAuthenticatingFilter{privatefinalLoggerlog=LoggerFactory.getLogger(JwtAuthFilter.class);//10分钟后刷新tokenprivatestaticfinalinttokenRefreshInterval=60*10;@OverrideprotectedbooleanpreHandle(ServletRequestrequest,ServletResponseresponse)throwsException{HttpServletRequesthttpServletRequest=WebUtils.toHttp(request);if(httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name()))//对于OPTION请求做拦截,不做token校验returnfalse;returnsuper.preHandle(request,response);}@OverrideprotectedvoidpostHandle(ServletRequestrequest,ServletResponseresponse){request.setAttribute("jwtShiroFilter.FILTERED",true);}@OverrideprotectedbooleanisAccessAllowed(ServletRequestrequest,ServletResponseresponse,ObjectmappedValue){if(this.isLoginRequest(request,response)){returntrue;}BooleanafterFiltered=(Boolean)(request.getAttribute("jwtShiroFilter.FILTERED"));if(BooleanUtils.isTrue(afterFiltered))returntrue;booleanallowed=false;try{allowed=executeLogin(request,response);}catch(IllegalStateExceptione){//not found any tokenlog.error("Not found any token");}catch(Exceptione){log.error("Error occurs when login",e);}returnallowed||super.isPermissive(mappedValue);}@OverrideprotectedAuthenticationTokencreateToken(ServletRequestservletRequest,ServletResponseservletResponse){StringjwtToken=getAuthzHeader(servletRequest);if(StringUtils.isNotBlank(jwtToken)&&!JWTUtil.isTokenExpired(jwtToken))returnUserLoginToken.buildPassword(jwtToken,null,"jwt");returnnull;}@OverrideprotectedbooleanonAccessDenied(ServletRequestservletRequest,ServletResponseservletResponse)throwsException{HttpServletResponsehttpResponse=WebUtils.toHttp(servletResponse);httpResponse.sendRedirect("/unauth");returnfalse;}@OverrideprotectedbooleanonLoginSuccess(AuthenticationTokentoken,Subjectsubject,ServletRequestrequest,ServletResponseresponse){HttpServletResponsehttpResponse=WebUtils.toHttp(response);if(tokeninstanceofUserLoginToken&&"jwt".equalsIgnoreCase(((UserLoginToken)token).getLoginType())){UserLoginTokenjwtToken=(UserLoginToken)token;booleanshouldRefresh=shouldTokenRefresh(Objects.requireNonNull(JWTUtil.getIssuedAt(jwtToken.getUsername())));if(shouldRefresh){//生成新的TOKENSecurityUseruser=(SecurityUser)subject.getPrincipal();StringnewToken=JWTUtil.sign(user.getUserInfo().getId());httpResponse.setHeader("x-auth-token",newToken);}}returntrue;}@OverrideprotectedbooleanonLoginFailure(AuthenticationTokentoken,AuthenticationExceptione,ServletRequestrequest,ServletResponseresponse){log.error("Validate token fail, token:{}, error:{}",token.toString(),e.getMessage());returnfalse;}/**

    * 获取TOKEN

    * @param request 请求

    * @return token

    */privateStringgetAuthzHeader(ServletRequestrequest){HttpServletRequesthttpRequest=WebUtils.toHttp(request);Stringheader=httpRequest.getHeader("x-auth-token");returnStringUtils.removeStart(header,"Bearer ");}/**

    * 判断是否需要刷新TOKEN

    * @param issueAt token签发日期

    * @return 是否需要刷新TOKEN

    */privatebooleanshouldTokenRefresh(DateissueAt){LocalDateTimeissueTime=LocalDateTime.ofInstant(issueAt.toInstant(),ZoneId.systemDefault());returnLocalDateTime.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';}//获取返回的TOKENconsttoken=response.headers['x-auth-token'];if(token){//将续期的TOKEN存起来localStorage.setItem("token",token);}// 这里是填写处理信息returnresponse;},(err)=>{// 这里是返回状态码不为200时候的错误处理console.log(err);if(err&&err.response){switch(err.response.data.code){case400:err.message='请求错误';break;case401:err.message='未授权,请登录';break;case403:err.message='无权限';break;case404:err.message=`请求地址出错: ${err.response.config.url}`;break;case408:err.message='请求超时';break;case500:err.message='服务器内部错误';break;case501:err.message='服务未实现';break;case502:err.message='网关错误';break;case503:err.message='服务不可用';break;case504:err.message='网关超时';break;case505:err.message='HTTP版本不受支持';break;default:}}Vue.prototype.$message.error(err.response.data.msg!=null?err.response.data.msg:err.message);returnPromise.reject(err)});

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容