当前位置:网站首页>Scheme and implementation of automatic renewal of token expiration
Scheme and implementation of automatic renewal of token expiration
2022-07-02 05:57:00 【Want to eat pineapple crisp】
Solution
programme 1: Every time a request is made, a new token【 The frequency is too high , Poor performance 】
programme 2: Generate two each time you log in token Return to the front end , One is used to identify users token, Another one token Is for refresh token With
programme 3: Return to the front end after login token And set the expiration time 30 minute , Each time a request is made, the front end puts token It is stored in the request header to send a request , When the back-end receives a request, it gets the request header for processing jwt Analyze and judge whether the expiration time is less than 10 minute , If it is less than 10 Minutes to generate a new token stay responseHearde Just go back
Scheme 2 implementation
Implementation process :
- After successful login , Backend return access_token and refresh_token, The client caches these two types of data token;
- Use access_token Request interface resources , Successful call ; If token Overtime , The client carries refresh_token call token Refresh interface to get new data access_token;
- The backend accepts the refresh token After request , Check refresh_token Is it overdue . If expired , Refuse to refresh , After the client receives the status , Go to the landing page ; If not expired , Generate a new access_token Return to the client .
- The client carries new access_token Call the above resource interface again .
- After the client logs out or changes the password , Write off old token, send access_token and refresh_token invalid , At the same time, clear the client access_token and refresh_toke.
Back end
LoginController In the controller
package com.liu.token.controller;
import com.liu.token.domain.Login;
import com.liu.token.utlis.JwtUtil;
import com.liu.token.utlis.ResponseResult;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
@RestController
@RequestMapping("/user")
public class LoginController {
@PostMapping("/login")
public ResponseResult login(@RequestBody Login login){
// Verification certificate ,1 minute
String access_token = JwtUtil.createJWT(login.getUsername(), 60*1000l);
// Verify that the certificate expires. Use this to refresh the certificate ,30 God
String refresh_token = JwtUtil.createJWT(login.getUsername(), 30*24*60*60*1000l);
HashMap<String,String> map=new HashMap<>();
map.put("access_token",access_token);
map.put("refresh_token",refresh_token);
return new ResponseResult(200," Login successful !",map);
}
// Verify routing , Is not important , Just provide access
@PostMapping("/logout")
public ResponseResult logout(){
HashMap<String,Object> map=new HashMap<>();
map.put("access_token",123456);
map.put("refresh_token",123456);
return new ResponseResult(200,"llalaallaal",map);
}
}
LoginFilter In the filter
package com.liu.token.filter;
import com.alibaba.fastjson.JSON;
import com.liu.token.common.CustomException;
import com.liu.token.utlis.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
@Slf4j
@WebFilter
public class LoginFilter implements Filter {
// Path matcher
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、 Get this request's URI
String requestURI = request.getRequestURI();
log.info(" Intercept request :{}", requestURI);
// Define the request path that does not need to be processed
String[] urls = new String[]{
"/user/login"
};
//2、 Judge whether this request needs to be processed
boolean check = check(urls, requestURI);
//3、 If it doesn't need to be dealt with , Then direct release
if (check) {
log.info(" This request {} No need to deal with ", requestURI);
filterChain.doFilter(request, response);
return;
}
String access_token = request.getHeader("access_token");
String refresh_token = request.getHeader("refresh_token");
if (access_token==null||refresh_token==null){
throw new CustomException(" No sign in , Please log in !");
}
HashMap<String,Object> map = new HashMap();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try {
// If it expires, an error will be reported , Will execute catch Code block
Claims claims = JwtUtil.parseJWT(access_token);
} catch (Exception e) {
try {
Claims claims = JwtUtil.parseJWT(refresh_token);
System.out.println(claims);
String id = claims.get("sub").toString();
String jwt = JwtUtil.createJWT(id, 60 * 1000l);
map.put("code",401);
map.put("msg"," Refresh token");
map.put("data",jwt);
response.getWriter().write(JSON.toJSONString(map));
response.getWriter().close();
} catch (Exception ex) {
map.put("code",402);
map.put("msg","token It's overdue , Please login again !");
map.put("data",null);
response.getWriter().write(JSON.toJSONString(map));
response.getWriter().close();
}
}
filterChain.doFilter(request, response);
}
/** * Path matching , Check whether this request needs to be released * * @param urls * @param requestURL * @return */
public boolean check(String[] urls, String requestURL) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURL);
if (match) {
return true;
}
}
return false;
}
}
front end
login.vue Log in to the test page
<template>
<div class="home">
<input type="text" v-model="username">
<input type="text" v-model="password">
<button @click="login"> Sign in </button>
</div>
<div>
<button @click="logout"> test </button>
</div>
</template>
<script> import request from "@/config/request" export default {
data() {
return {
username:"123456", password:"123456", } }, methods: {
login() {
request.post("/user/login", {
username: this.username, password:this.password }).then(res => {
let {
code, msg, data } = res; console.log(data); if (code == 200) {
// preservation token window.localStorage.setItem("access_token",data.access_token) window.localStorage.setItem("refresh_token",data.refresh_token) } }) }, logout() {
request.post("/user/logout", {
username: this.username, password:this.password }).then(res => {
let {
code, msg, data } = res; console.log(res); }) } } } </script>
request.js
// Import axios and qs plug-in unit
import axios from "axios"
import qs from "qs"
// Configure the global public domain name
// const baseURL = process.env.NODE_ENV === "production" ? "https://www.xxxxx.com" : "";
// establish axios example
let request = axios.create({
baseURL: "/api", // Assign a public domain name
timeout: 5000 // Set the delay time ( Company : millisecond )
})
// Intercept request Send requests and respond to requests , And do some configuration
request.interceptors.request.use(
// Intercept send request , And give the request header information headers add token token
config => {
config.headers["access_token"] = localStorage.getItem("access_token");
config.headers["refresh_token"] = localStorage.getItem("refresh_token");
return config
},
err => {
Promise.reject(err)
}
)
request.interceptors.response.use(
// Intercept response requests , Data is directly returned here
response => {
console.log(response)
// console.log(response.headers)
if (response.data.code == 200) {
return response.data;
} else if (response.data.code == 401) {
console.log("--------------------------------")
window.localStorage.setItem("access_token", response.data.data);
return request.request(response.config);
} else if (response.data.code == 402) {
alert(" Please login again ! Jump routing logic ")
}
},
err => {
Promise.reject(err)
}
)
// export request
export default request;
Implementation of scheme III
Back end
LoginController In the controller
package com.liu.token.controller;
import com.liu.token.domain.Login;
import com.liu.token.utlis.JwtUtil;
import com.liu.token.utlis.ResponseResult;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/login")
public ResponseResult login(@RequestBody Login login){
// Verification certificate ,11 minute
String access_token = JwtUtil.createJWT(login.getUsername(), 30*60*1000l);
HashMap<String,String> map=new HashMap<>();
map.put("access_token",access_token);
return new ResponseResult(200," Login successful !",map);
}
// Verify routing , Is not important , Just provide access
@PostMapping("/logout")
public ResponseResult logout(){
HashMap<String,Object> map=new HashMap<>();
map.put("access_token",123456);
map.put("refresh_token",123456);
return new ResponseResult(200,"llalaallaal",map);
}
}
LoginFilter In the filter
package com.liu.token.filter;
import com.alibaba.fastjson.JSON;
import com.liu.token.common.CustomException;
import com.liu.token.utlis.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
@Slf4j
@WebFilter
public class LoginFilter implements Filter {
// Path matcher
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、 Get this request's URI
String requestURI = request.getRequestURI();
log.info(" Intercept request :{}", requestURI);
// Define the request path that does not need to be processed
String[] urls = new String[]{
"/user/login"
};
//2、 Judge whether this request needs to be processed
boolean check = check(urls, requestURI);
//3、 If it doesn't need to be dealt with , Then direct release
if (check) {
log.info(" This request {} No need to deal with ", requestURI);
filterChain.doFilter(request, response);
return;
}
String access_token = request.getHeader("access_token");
if (access_token==null){
throw new CustomException(" No sign in , Please log in !");
}
try {
Claims claims = JwtUtil.parseJWT(access_token);
int exp = (int)claims.get("exp");
String id = claims.get("sub").toString();
long minute = (exp*1000l - System.currentTimeMillis())/1000/60;
// also 10 Update when minutes expire token
if (minute<10){
String token = JwtUtil.createJWT(id, 30 * 60 * 1000l);
response.addHeader("token",token);
}
} catch (Exception e) {
HashMap<String,Object> map = new HashMap();
map.put("code",402);
map.put("msg","token Has expired , Log back in !");
map.put("data",null);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().write(JSON.toJSONString(map));
response.getWriter().close();
}
filterChain.doFilter(request, response);
}
/** * Path matching , Check whether this request needs to be released * * @param urls * @param requestURL * @return */
public boolean check(String[] urls, String requestURL) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURL);
if (match) {
return true;
}
}
return false;
}
}
front end
login.vue Log in to the test page
<template>
<div class="home">
<input type="text" v-model="username">
<input type="text" v-model="password">
<button @click="login"> Sign in </button>
</div>
<div>
<button @click="logout"> test </button>
</div>
</template>
<script> import request from "@/config/request" export default {
data() {
return {
username:"123456", password:"123456", } }, methods: {
login() {
request.post("/user/login", {
username: this.username, password:this.password }).then(res => {
let {
code, msg, data } = res; console.log(data); if (code == 200) {
window.localStorage.setItem("access_token",data.access_token) } }) }, logout() {
request.post("/user/logout", {
username: this.username, password:this.password }).then(res => {
let {
code, msg, data } = res; console.log(res); }) } } } </script>
request.js
// Import axios and qs plug-in unit
import axios from "axios"
import qs from "qs"
// Configure the global public domain name
// const baseURL = process.env.NODE_ENV === "production" ? "https://www.xxxxx.com" : "";
// establish axios example
let request = axios.create({
baseURL: "/api", // Assign a public domain name
timeout: 5000 // Set the delay time ( Company : millisecond )
})
// Intercept request Send requests and respond to requests , And do some configuration
request.interceptors.request.use(
// Intercept send request , And give the request header information headers add token token
config => {
config.headers["access_token"] = localStorage.getItem("access_token");
return config
},
err => {
Promise.reject(err)
}
)
request.interceptors.response.use(
// Intercept response requests , Data is directly returned here
response => {
console.log(response)
if (response.data.code == 200) {
// If the response header has token Just save it
let token = response.headers["token"];
if (token) {
window.localStorage.setItem("access_token", token);
}
return response.data;
} else if (response.data.code == 402) {
alert(" Please login again ! Jump routing logic ")
}
},
err => {
Promise.reject(err)
}
)
// export request
export default request;
边栏推荐
- php内类名称与类内方法名相同
- 1037 Magic Coupon
- Stc8h8k series assembly and C51 actual combat - digital display ADC, key serial port reply key number and ADC value
- Stick to the big screen UI, finereport development diary
- Grbl software: basic knowledge of simple explanation
- File contains vulnerabilities (II)
- RGB infinite cube (advanced version)
- mysql事务和隔离级别
- 文件包含漏洞(二)
- 文件包含漏洞(一)
猜你喜欢

51单片机——ADC讲解(A/D转换、D/A转换)

深度学习分类网络--Network in Network

TI毫米波雷达学习(一)

Balsamiq wireframes free installation

软件测试 - 概念篇

15 C language advanced dynamic memory management

OLED12864 液晶屏

uni-app开发中遇到的问题(持续更新)

Brain and cognitive neuroscience matlab psychoolbox cognitive science experimental design - experimental design 4

测试 - 用例篇
随机推荐
PHP array to XML
Addchild() and addattribute() functions in PHP
vite如何兼容低版本浏览器
死磕大屏UI,FineReport开发日记
Lantern Festival gift - plant vs zombie game (realized by Matlab)
Lambda 表达式 和 方法引用
数据挖掘方向研究生常用网站
Redis Key-Value数据库 【高级】
Pytorch Chinese document
PHP inner class name is the same as the inner class method name
数据库学习总结5
"Simple" infinite magic cube
mysql的约束总结
JS determines whether the mobile terminal or the PC terminal
PHP parent
Ti millimeter wave radar learning (I)
[whether PHP has soap extensions installed] a common problem for PHP to implement soap proxy: how to handle class' SoapClient 'not found in PHP
Stc8h8k Series Assembly and c51 Real combat - NIXIE TUBE displays ADC, Key Series port reply Key number and ADC value
Vite打包后的dist不能直接在浏览器打开吗
OLED12864 液晶屏