当前位置:网站首页>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;
边栏推荐
- 《CGNF: CONDITIONAL GRAPH NEURAL FIELDS》阅读笔记
- Regular expression summary
- 【LeetCode】Day92-盛最多水的容器
- How vite is compatible with lower version browsers
- Unity shader learning notes (3) URP rendering pipeline shaded PBR shader template (ASE optimized version)
- [C language] simple implementation of mine sweeping game
- Redis key value database [primary]
- Practice C language advanced address book design
- c语言中的几个关键字
- “簡單”的無限魔方
猜你喜欢

文件包含漏洞(一)

软件测试 - 概念篇

神机百炼3.54-染色法判定二分图

Memcached installation

数理统计与机器学习

【論文翻譯】GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond

正则表达式总结

Lingyunguang rushes to the scientific innovation board: the annual accounts receivable reaches 800million. Dachen and Xiaomi are shareholders

Huawei Hongmeng OS, is it OK?

文件包含漏洞(二)
随机推荐
PHP gets CPU usage, hard disk usage, and memory usage
Software testing Q & A
GRBL 软件:简单解释的基础知识
Redis key value database [advanced]
Go language web development is very simple: use templates to separate views from logic
Some descriptions of Mipi protocol of LCD
Huawei Hongmeng OS, is it OK?
Lambda 表达式 和 方法引用
Oled12864 LCD screen
VSCode paste image插件保存图片路径设置
492.构造矩形
RGB 无限立方体(高级版)
数据挖掘方向研究生常用网站
Ti millimeter wave radar learning (I)
PHP obtains some values in the string according to the specified characters, and reorganizes the remaining strings into a new array
使用sha256文件验证下载的文件
External interrupts cannot be accessed. Just delete the code and restore it Record this unexpected bug
[C language] simple implementation of mine sweeping game
Unity shader learning notes (3) URP rendering pipeline shaded PBR shader template (ASE optimized version)
Fundamentals of software testing