1, Causes and working principle of jwt
1. What is JWT
JSON Web Token (JWT), which is currently the most popular cross domain authentication solution
2. Why JWT
The essence of JWT is "decentralization", and the data is stored on the client.
3. Working principle of JWT
1. After server authentication, a JSON object will be generated and sent back to the user, as shown in the following example:
{"UserName": "Chongchong","Role": "Admin","Expire": "2018-08-08 20:15:56"}
2. Then, when the user communicates with the server, the client sends back the JSON object in the request
3. In order to prevent the user from tampering with the data, the server will add a signature when generating the object and verify the returned data
4. JWT composition
A JWT is actually a string, which consists of three parts: header, payload and signature (signature)
Schematic diagram of JWT structure: see "JWT data structure. jpg"
Actual structure of JWT: eyJhbGciOiJIUzI1NiJ9
eyJzdWIiOiJ7fSIsImlzcyI6InpraW5nIiwiZXhwIjoxNTYyODUwMjM3LCJpYXQiOjE1NjI4NDg0MzcsImp0aSI6ImM5OWEyMzRmMDc4NzQyZWE4YjlmYThlYmYzY2VhNjBlIiwidXNlcm5hbWUiOiJ6c3MifQ.
WUfqhFTeGzUZCpCfz5eeEpBXBZ8-lYg1htp-t7wD3I4
It is a very long string, separated into three parts by dots (.). Note that there is no newline inside JWT. This is just for For ease of presentation, write it in a few lines.
In one line, it looks like the following: Header.Payload.Signature
4.1 Header
{"typ":"JWT","alg":"HS256"}
The typ attribute in this json is used to identify that the entire token string is a JWT string; Its alg attribute is used to describe the signature and digest algorithm used when issuing the JWT
The full names of typ and alg attributes are actually type and algorithm, which mean type and algorithm respectively. The reason why they are all represented by three letters is also based on the final string size of JWT Worry,
At the same time, it is consistent with the name of JWT, so it is all three characters... typ and alg are the attribute names specified in the JWT standard
4.2 payload
{"sub":"123","name":"Tom","admin":true}
payload is used to carry the data to be transferred. Its json structure is actually a set of declarations for the data to be transferred by JWT. These declarations are called claims by the JWT standard,
Its "attribute value pair" is actually a claim,
Each claim represents a specific meaning and function.
4.3 signature
Signature is the two strings obtained by base64url encoding the json structure corresponding to the header and payload, which are spliced with English sentence point numbers, and then specified according to the alg in the header Generated by the signature algorithm.
Different algorithms lead to different signature results. Take alg: HS256 as an example to illustrate how the previous signature is obtained.
5. Verification process of JWT
Its verification method is actually very simple. As long as you decode the header base64url, you can know what algorithm JWT uses to make the signature, and then use this algorithm to use the same logic again Header and payload sign once,
And compare whether the signature is exactly the same as the string of the third part contained in the JWT itself. As long as it is different, it can be considered that the JWT is a tampered string, which naturally belongs to verification failure Yes.
The receiver must use the same key as the JWT sender when generating the signature
Note 1: when verifying a JWT, signature authentication will be done automatically by each implementation library, but the authentication of payload is determined by the user. Because JWT may contain a custom claim,
Therefore, it will not automatically verify these claim s. Take jjwt-0.7.0.jar as an example:
A if the signature authentication fails, the following exception will be thrown:
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
That is, the signature is wrong. The signature of JWT does not match the signature of the local computer
B JWT expiration exception
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2017-06-13T11:55:56Z. Current time: 2017-06-13T11:55:57Z, a difference of 1608 milliseconds. Allowed
Note 2: if authentication fails, 401 Unauthorized response is returned
Note 3: as a Middleware HOOK, the authentication service intercepts the request. First, look up the Token information in the cookie. If it is not found, it will be in HTTP Authorization Find in Head
6. JWT token refresh idea
6.1 after successful login, return the generated JWT token to the client through the response header
6.2 each time the web app project requests background data (bring the JWT token from the request header),
If the verification is passed, refresh the JWT, save it in the response header and return it to the client. The effective time is 30 minutes
JwtFilter
Note 1: modify CorsFilter and add a new request header "jwt" allowed
Note 2: originally, on the default request, the browser can only access the following default response headers
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
If you want the browser to access other response headers, you need to set access control expose headers on the server
Access-Control-Expose-Headers : 'jwt'
// CorsFilter allows the client to send a new request header jwt
resp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With, Content-Type, Accept, jwt");
Note 3: axios obtains the jwt token from the response header and saves it to vuex
Here is a problem: how to obtain the root instance of Vue in the project. The solution: modify main.js
window.vm = new Vue({...});
The access restrictions of traditional development on resources are illustrated by using session:
Problems and mechanisms solved by jwt:
web.xml: filters to solve jwt problems:
<!-- solve jwt Problem filter --> <filter> <filter-name>jwtFilter</filter-name> <filter-class>com.zking.vue.util.JwtFilter</filter-class> </filter> <filter-mapping> <filter-name>jwtFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
JwtFilter.java: enable jwt token verification function:
private boolean OFF = false;//true turns off jwt token verification, and false turns on
package com.zking.vue.util; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import io.jsonwebtoken.Claims; /** * * JWT Verify the filter, configuration sequence: corsfilte -- > jwtfilter -- > Struts2 central controller * * @author Administrator * */ public class JwtFilter implements Filter { // Excluded URL, usually the login URL (please change it to your own login URL) private static String EXCLUDE = "^/vue/userAction_login\\.action?.*$"; private static Pattern PATTERN = Pattern.compile(EXCLUDE); private boolean OFF = false;//true turns off jwt token verification, and false turns on @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String path = req.getServletPath(); if (OFF || isExcludeUrl(path)) {// Landing direct release chain.doFilter(request, response); return; } // Get the token from the client request header and verify it String jwt = req.getHeader(JwtUtils.JWT_HEADER_KEY); Claims claims = this.validateJwtToken(jwt); if (null == claims) { // resp.setCharacterEncoding("UTF-8"); resp.sendError(403, "JWT The token has expired or expired"); return; } else { String newJwt = JwtUtils.copyJwt(jwt, JwtUtils.JWT_WEB_TTL); resp.setHeader(JwtUtils.JWT_HEADER_KEY, newJwt); chain.doFilter(request, response); } } /** * Verify the jwt token by returning the declaration (including public and private). If null is returned, the verification fails */ private Claims validateJwtToken(String jwt) { Claims claims = null; try { if (null != jwt) { claims = JwtUtils.parseJwt(jwt); } } catch (Exception e) { e.printStackTrace(); } return claims; } /** * Is this an excluded URL * * @param path * @return */ private boolean isExcludeUrl(String path) { Matcher matcher = PATTERN.matcher(path); return matcher.matches(); } // public static void main(String[] args) { // String path = "/sys/userAction_doLogin.action?username=zs&password=123"; // Matcher matcher = PATTERN.matcher(path); // boolean b = matcher.matches(); // System.out.println(b); // } }
Useraction. Java: insert jwt token into response header
// Map<String, Object> claims = new HashMap<String, Object>(); // claims.put("uname",user.getUname()); // claims.put("pwd", user.getPwd()); // String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL); // response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);
package com.zking.vue.web; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import com.opensymphony.xwork2.ModelDriven; import com.zking.base.web.BaseAction; import com.zking.vue.biz.UserBiz; import com.zking.vue.entity.User; import com.zking.vue.util.JsonData; import com.zking.vue.util.JwtUtils; import com.zking.vue.util.PageBean; import com.zking.vue.util.ResponseUtil; import com.zking.vue.util.StringUtils; public class UserAction extends BaseAction implements ModelDriven<User>{ private UserBiz userBiz; private User user = new User(); public UserBiz getUserBiz() { return userBiz; } public void setUserBiz(UserBiz userBiz) { this.userBiz = userBiz; } public String login() { ObjectMapper om = new ObjectMapper(); JsonData jsonData = null; try { if(StringUtils.isBlank(user.getUname()) || StringUtils.isBlank(user.getPwd())) { jsonData = new JsonData(0, "User or password is empty", user); }else { User u = this.userBiz.login(user); Map<String, Object> claims = new HashMap<String, Object>(); claims.put("uname",user.getUname()); claims.put("pwd", user.getPwd()); String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL); response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt); jsonData = new JsonData(1, "Login succeeded", u); } } catch (Exception e) { e.printStackTrace(); jsonData = new JsonData(0, "User or password error", user); }finally { try { ResponseUtil.write(response, om.writeValueAsString(jsonData)); } catch (Exception e) { e.printStackTrace(); } } return null; } public String getAsyncData() { ObjectMapper om = new ObjectMapper(); try { Thread.sleep(6000); ResponseUtil.write(response, om.writeValueAsString("http://www.javaxl.com")); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public User getModel() { return user; } }
403 error:
1. Restricted, restricted access and did not get the voucher;
2. It will also appear when you are a crawler. The IP is blocked and there is no certificate;
3. Being blacklisted;
The jwt token response header is in the browser, and the front-end code is not obtained
The front-end project http.js gets all the response header information:
// Response interceptor axios.interceptors.response.use(function(response) { // debugger; // var jwt = response.headers['jwt']; // if(jwt){ // window.vm.$store.commit('setJwt',{jwt:jwt}); // } return response; }, function(error) { return Promise.reject(error); });
/** * vue Project global configuration for axios */ import axios from 'axios' import qs from 'qs' //The action module is introduced and added to the class attribute urls of axios import action from '@/api/action' axios.urls = action // axios default configuration axios.defaults.timeout = 10000; // Timeout // axios.defaults.baseURL = 'http://localhost:8080/j2ee15 '; // Default address axios.defaults.baseURL = action.SERVER; //Organize data // Only applicable to POST,PUT,PATCH, transformRequest ` allows you to modify the request data before sending it to the server axios.defaults.transformRequest = function(data) { data = qs.stringify(data); return data; }; // request interceptor axios.interceptors.request.use(function(config) { var jwt = window.vm.$store.getters.getJwt; config.headers['jwt'] = jwt; return config; }, function(error) { return Promise.reject(error); }); // Response interceptor axios.interceptors.response.use(function(response) { // debugger; var jwt = response.headers['jwt']; if(jwt){ window.vm.$store.commit('setJwt',{jwt:jwt}); } return response; }, function(error) { return Promise.reject(error); }); // //Route request interception // //http request interceptor // axios.interceptors.request.use( // config => { // //config.data = JSON.stringify(config.data); // //config.headers['Content-Type'] = 'application/json;charset=UTF-8'; // //config.headers['Token'] = 'abcxyz'; // //Judge whether there is a ticket. If so, add a ticket to each http header // // if (cookie.get("token")) { // // // The user sets the cookie to 2 hours for each operation // // cookie.set("token", cookie.get("token"), 1 / 12) // // cookie.set("name", cookie.get("name"), 1 / 12) // // config.headers.token = cookie.get("token"); // // config.headers.name = cookie.get("name"); // // } // return config; // }, // error => { // return Promise.reject(error.response); // }); // //Route response interception // //http response interceptor // axios.interceptors.response.use( // response => { // if (response.data.resultCode == "404") { // console.log("response.data.resultCode is 404") // //Return error code - 1, clear the ticket information and jump to the login page // // cookie.del("ticket") // // window.location.href='http://login.com' // return // } else { // return response; // } // }, // error => { // return Promise.reject(error.response) / / returns the error information returned by the interface // }); export default axios;
Write to the front-end variables.js:
setJwt: (state, payload) => { state.Jwt = payload.Jwt; },
Put the value of jwt token into vuex:
Set the value through changes.js and write the setJwt method:
This keyword can only appear in vue components. In js, the function of vuex to be called window.vm(vm can take it at will) represents this
Mutations.js:
// Variable modification export default { setResturantName: (state, payload) => { //payload: load: actually, it is a container for saving parameters to be transferred, which is an object state.resturantName = payload.resturantName; }, setJwt: (state, payload) => { state.Jwt = payload.Jwt; }, doAjax:(state,payload)=>{ //Requirements: you want to interact with the background server in the current file let _this = payload._this; let url = _this.axios.urls.SYSTEM_MENU_TREE; _this.axios.post(url, {}).then((resp) =>{ console.log(resp); _this.menus = resp.data.result; }).catch(function(error) { console.log(error); }); } }
State.js defines jwt variables:
/* Variable definition */ export default{ resturantName:'LongQin Bay' jwt:'' }
Getters.js defines the getjwt acquisition method:
export default{ getResturantName:(state)=>{ return state.resturantName; }, getJwt:(state)=>{ return state.Jwt; } }
main.js:
window.vm = new Vue({//At this point, window.vm represents the root instance of Vue
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' // process.env.MOCK && require('@/mock') import 'element-ui/lib/theme-chalk/index.css' // New addition two import App from './App' import router from './router' import ElementUI from 'element-ui' // New addition one import axios from '@/api/http' //#Global configuration of axios by vue project // import axios from 'axios' import VueAxios from 'vue-axios' import store from './store' Vue.use(ElementUI) // New addition three Vue.use(VueAxios,axios) Vue.config.productionTip = false /* eslint-disable no-new */ window.vm = new Vue({//At this point, window.vm represents the root instance of Vue el: '#app', data(){ return { Bus:new Vue({ /*There's no need to write here */ }) } }, router, store, components: { App }, template: '<App/>' })
Bring the value of jwt into the request header when requesting
Release the http.js request Interceptor:
// request interceptor axios.interceptors.request.use(function(config) { var jwt = window.vm.$store.getters.getJwt; config.headers['jwt'] = jwt; return config; }, function(error) { return Promise.reject(error); });
Bring the value of jwt into the request header the second time
Release the http.js request Interceptor:
// request interceptor axios.interceptors.request.use(function(config) { var jwt = window.vm.$store.getters.getJwt; config.headers['jwt'] = jwt; return config; }, function(error) { return Promise.reject(error); });
Get method defined in Getters.js
export default{ getResturantName:(state)=>{ return state.resturantName; }, getJwt:(state)=>{ return state.Jwt; } }
Question:
In a browser, after logging in to the home page,
Open an interface again, copy the home page link, open the home page, and you can't access the home page,
reason:
The first time there is no jwt in the request header, then the request background server generates a jwt and returns it. At this time, there is a jwt in the response header,
There is jwt in the second access request header, which is used for the second time by taking the first response header. After returning, it is brought back when requesting. Each request is the last one,
When a new interface is opened, there is no jwt in the request header, so it cannot be accessed; The requests in the two request headers are different
Therefore, jwt is more secure than session
2, jwt tool class introduction, three scenarios
1. jwt tool class
The jwt token contains:
Payload: user information
Signature: it's the codebook
jwtUtils:
parseJwt method: parse the unreadable string into user information;
createJwt method: change the user information into an incomprehensible string;
package com.zking.vue.util; import java.util.Date; import java.util.Map; import java.util.UUID; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; /** * JWT Validation filter: configuration order corsfilte - > jwtutilsr -- > strutsprepareandexecutefilter * */ public class JwtUtils { /** * JWT_WEB_TTL: WEBAPP The effective time of the token in the application, which is 30 minutes by default */ public static final long JWT_WEB_TTL = 30 * 60 * 1000; /** * Save the jwt token to the key in the header */ public static final String JWT_HEADER_KEY = "jwt"; // The signature algorithm used when specifying the signature, that is, the header part, jjwt has encapsulated this part. private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256; private static final String JWT_SECRET = "f356cdce935c42328ad2001d7e9552a3";// JWT key private static final SecretKey JWT_KEY;// Encryption key generated using JWT key static { byte[] encodedKey = Base64.decodeBase64(JWT_SECRET); JWT_KEY = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); } private JwtUtils() { } /** * Decrypt jwt to get all declarations (including standard and private declarations) * * @param jwt * @return * @throws Exception */ public static Claims parseJwt(String jwt) { Claims claims = Jwts.parser().setSigningKey(JWT_KEY).parseClaimsJws(jwt).getBody(); return claims; } /** * Create a JWT token, and the issuing time is the current time * * @param claims * Create a payload private statement (add it according to specific business needs. If you want to use this for verification, you generally need to communicate the verification method with the jwt receiver in advance) * @param ttlMillis * JWT The effective time (in milliseconds), current time + effective time = expiration time * @return jwt token */ public static String createJwt(Map<String, Object> claims, long ttlMillis) { // The time when the JWT was generated, that is, the issuing time long nowMillis = System.currentTimeMillis(); // The following is to add various standard declarations and private declarations for payload // This is actually a new JwtBuilder to set jwt's body JwtBuilder builder = Jwts.builder() // If there is a private declaration, you must first set the private declaration created by yourself. This is to assign a value to the builder's claim. Once it is written after the assignment of the standard declaration, it overwrites those standard declarations .setClaims(claims) // Set jti(JWT ID): it is the unique ID of JWT. According to business needs, this can be set as a non duplicate value, which is mainly used as a one-time token to avoid replay attacks. // It can be used as an ID before logging in .setId(UUID.randomUUID().toString().replace("-", "")) // ISS (issuer), write dead // .setIssuer("zking") // IAT: issuing time of JWT .setIssuedAt(new Date(nowMillis)) // Represents the main body of the JWT, that is, its owner. This is a json format string that can put data {"uid":"zs"}. Not here // .setSubject("{}") // Set the signature algorithm and secret key used for signature .signWith(SIGNATURE_ALGORITHM, JWT_KEY) // Set JWT expiration time .setExpiration(new Date(nowMillis + ttlMillis)); return builder.compact(); } /** * Copy jwt and reset the issue time (current time) and expiration time * * @param jwt * jwt token copied * @param ttlMillis * jwt The effective time (in milliseconds), current time + effective time = expiration time * @return */ public static String copyJwt(String jwt, Long ttlMillis) { Claims claims = parseJwt(jwt); // The time when the JWT was generated, that is, the issuing time long nowMillis = System.currentTimeMillis(); // The following is to add various standard declarations and private declarations for payload // This is actually a new JwtBuilder to set jwt's body JwtBuilder builder = Jwts.builder() // If there is a private declaration, you must first set the private declaration created by yourself. This is to assign a value to the builder's claim. Once it is written after the assignment of the standard declaration, it overwrites those standard declarations .setClaims(claims) // Set jti(JWT ID): it is the unique ID of JWT. According to business needs, this can be set as a non duplicate value, which is mainly used as a one-time token to avoid replay attacks. // It can be used as an ID before logging in //.setId(UUID.randomUUID().toString().replace("-", "")) // ISS (issuer), write dead // .setIssuer("zking") // IAT: issuing time of JWT .setIssuedAt(new Date(nowMillis)) // Represents the main body of the JWT, that is, its owner. This is a json format string that can put data {"uid":"zs"}. Not here // .setSubject("{}") // Set the signature algorithm and secret key used for signature .signWith(SIGNATURE_ALGORITHM, JWT_KEY) // Set JWT expiration time .setExpiration(new Date(nowMillis + ttlMillis)); return builder.compact(); } }
Three scenarios:
jwtDemo:
package com.zking.vue.test; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.junit.Test; import com.zking.vue.util.JwtUtils; import io.jsonwebtoken.Claims; public class JwtDemo { private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); @Test public void test1() {// Generate JWT Map<String, Object> claims = new HashMap<String, Object>(); claims.put("username", "zss"); claims.put("age", 18); String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL); System.out.println(jwt); Claims parseJwt = JwtUtils.parseJwt(jwt); for (Map.Entry<String, Object> entry : parseJwt.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } Date d1 = parseJwt.getIssuedAt(); Date d2 = parseJwt.getExpiration(); System.out.println("Token issuing time:" + sdf.format(d1)); System.out.println("Token expiration time:" + sdf.format(d2)); } @Test public void test2() {// Parse oldJwt // String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48"; String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM1MjU5MjMsImlhdCI6MTU2MzUyNDEyMywiYWdlIjoxOCwianRpIjoiOTAzNmMwY2Q3NGIwNDBjMzgzMDAxYzdiNmZkMzYzZmIiLCJ1c2VybmFtZSI6InpzcyJ9.sgV9fr4fgmmahDFRJnsfazA6R3H-gNMVcg2ucA227n4"; Claims parseJwt = JwtUtils.parseJwt(oldJwt); for (Map.Entry<String, Object> entry : parseJwt.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } Date d1 = parseJwt.getIssuedAt(); Date d2 = parseJwt.getExpiration(); System.out.println("Token issuing time:" + sdf.format(d1)); System.out.println("Token expiration time:" + sdf.format(d2)); } @Test public void test3() {// Copy jwt and delay 30 seconds String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48"; String jwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL); Claims parseJwt = JwtUtils.parseJwt(jwt); for (Map.Entry<String, Object> entry : parseJwt.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } Date d1 = parseJwt.getIssuedAt(); Date d2 = parseJwt.getExpiration(); System.out.println("Token issuing time:" + sdf.format(d1)); System.out.println("Token expiration time:" + sdf.format(d2)); } @Test public void test4() {// Test the effective time of JWT Map<String, Object> claims = new HashMap<String, Object>(); claims.put("username", "zss"); String jwt = JwtUtils.createJwt(claims, 3 * 1000L); System.out.println(jwt); Claims parseJwt = JwtUtils.parseJwt(jwt); Date d1 = parseJwt.getIssuedAt(); Date d2 = parseJwt.getExpiration(); System.out.println("Token issuing time:" + sdf.format(d1)); System.out.println("Token expiration time:" + sdf.format(d2)); } @Test public void test5() {// Parse the above token with an expiration time of only three seconds after three seconds, because if it expires, an error io.jsonwebtoken.ExpiredJwtException will be reported String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI4NTMzMzAsImlhdCI6MTU2Mjg1MzMyNywidXNlcm5hbWUiOiJ6c3MifQ.e098Vj9KBlZfC12QSDhI5lUGRLbNwb27lrYYSL6JwrQ"; Claims parseJwt = JwtUtils.parseJwt(oldJwt); // After expiration, the parsing will report an error, and the following code will not be executed at all Date d1 = parseJwt.getIssuedAt(); Date d2 = parseJwt.getExpiration(); System.out.println("Token issuing time:" + sdf.format(d1)); System.out.println("Token expiration time:" + sdf.format(d2)); } }
Result display of three scenarios
The first one is how to generate and parse jwt tokens through jwt tool classes
Second: jwt token expiration scenario
The third: the lifetime of the continuation token
The token expiration time is 30 minutes. If it has been in use, it will expire after 30 minutes and log in again. This is unreasonable
Therefore, it is necessary to set the last use time as the issuance time, and the later 30 minutes as the expiration time,
Solution: copy jwt token and reset the issue expiration time
The instruction is a new jwt instruction in the operation of the first method. It should be replaced. Otherwise, an error will be reported and the instruction expires
Well, vue's study is over!