A preface.

Remember that the last Spring Cloud article on how to disable JWT was a combination of theory and code practice, which I assumed would be the final article in the Spring Cloud-based unified authentication architecture series. But the other hot topic about JWT is JWT renewal? .

In this article, I would like to share with you a better JWT renewal plan and implementation, which is to throw away the jade. Welcome to leave a message if you have a good plan.

The back-end

  1. Spring Cloud of actual combat | first article: Windows setup Nacos services
  2. The second Spring Cloud of actual combat | : Spring Cloud integration Nacos registry
  3. Spring Cloud of actual combat | article 3: the Spring Cloud integration Nacos configuration center
  4. Spring Cloud of actual combat | article 4: Spring Cloud integration Gateway API Gateway
  5. Spring Cloud of actual combat | article 5: Spring Cloud integration OpenFeign between micro service calls
  6. Spring Cloud of actual combat | article 6: the Spring Cloud + Spring Security Gateway OAuth2 + JWT micro service unified certificate authority
  7. Spring Cloud of actual combat | the seven articles: Spring Cloud + Spring Security Gateway OAuth2 integrated unified certificate authority platform to realize the logout disable JWT scheme
  8. Spring Cloud of actual combat | the eight: Spring Cloud + Spring Security OAuth2 + Vue no refresh perception to realize the separation mode before and after JWT renewed

Management of the front

  1. Vue – element – admin combat | first article: remove the mock access background, building a youlai – mall to mall before and after the separation management platform
  2. Vue – element – the second admin combat | : minimal change access backend implementation according to the dynamic loading menu

Wechat applets

  1. Vue + uniapp mall real | first article: 【 】 has to store WeChat small programs to rapidly develop access Spring Cloud OAuth2 authentication center to complete the authorization to log in

2. Package

Theoretical Background: Under the background of unified authentication of microservices realized by Youlai-Mall microservice project OAuth2, the front end invokes/OAuth/Token interface authentication, and two tokens, Access_token and refresh_token, are returned after successful authentication. For security reasons, the validity period of Access_Token is much shorter than that of refresh_token. The default value of access_token is 12 hours, and the default value of refresh_token is 30 days. When the Access_Token expires or is about to expire, refresh_Token needs to be refreshed and a new Access_token is returned to the client. However, perception-free refresh is required for good customer experience.

Solution a:

The browser starts a timed polling task, refreshing each time before the access_token expires.

Scheme 2:

When the request returns an exception indicating that the Access_Token has expired, the browser sends a request for exchanging refresh_Token for access_token. After obtaining the new Access_token, the browser retries the request that fails because the Access_Token has expired.

Scheme comparison:

The first solution is simple to implement, but the old access_tokens can still be accessed before they expire. It is a waste of resources to blacklist these access_tokens.

The second solution is to refresh the access_token after it has expired, which will not have the above problems, but it will create an extra request, and the implementation of more problems to consider, such as how to deal with the request after the token refresh stage. How to retry these requests once the new access_token is obtained.

Conclusion: The first scheme is simple to implement; The second option is more rigorous. Expiration does not cause the access_token to remain valid. In short, both schemes are feasible. This paper explains how the second scheme realizes JWT renewal without perceptual refresh token through the coordination of the front and back ends.

3. Implement

The code is based on the Spring Cloud backend Youlai-mall and the Vue front-end Youlai-mall-admin. The code is based on the Spring Cloud backend Youlai-mall and Vue front-end Youlai-mall-admin. If you need it, you can download it to your local reference. If it is helpful to you, I also hope to give you a star. Thank you

The back-end

In the back-end part, the only work here is to throw a custom exception when gateway Youlai-gateway identifies the access_token expiration to provide the front-end judgment, as shown in the following figure:

How do you determine whether JWT has expired? Don’t worry, the following will explain, first look at the implementation and then say the principle.

The front end

1. OAuth2 client Settings

Set the OAuth2 client to support refresh mode so that refresh_token can be refreshed for a new Access_token. And set the expiration time of access_token and refresh_token respectively for our test, because the default 12 hours and 30 days are too much for us. In addition, it must also meet the condition that t(refresh_token) > 60s + T (access_token). The time of refresh_token is greater than that of access_token. The reasons will be explained below.

2. Add the refresh token method

After setting the client refresh mode, add a refreshToken method in the front end. The invoked interface is the same as the login authentication interface /oauth/token, but the value of authorization mode grant_type is changed from password to refresh_token. That is, the password mode is switched to refresh mode. After refreshing the token, the new token is written to localStorage to override the old token.

3. Request response interception adds token expiration processing

When the response result is that the token has expired, the refresh token method is executed to override the local token.

Two key variables have been added to meet the need to avoid repeated refreshes and request retries during the refresh:

  • Refreshing —- Refreshes the label

If the first access_token expiration request fails, this parameter is enabled when the request for token refresh is invoked. This parameter indicates that the access_token is being refreshed, avoiding repeated refreshing in subsequent requests due to token expiration.

  • WaitQueue —- Request waiting queue

During the token refresh period, subsequent requests need to be cached in the wait queue first. When the token refresh succeeds, the request in the wait queue can be re-executed.

Modify the request response package request.js code as follows, the key part of the use of annotations, complete project Youlai-mall -admin

Let refreshing = false, To avoid repetition and refresh waitQueue = [] / / request waiting queue service. The interceptors. Response. Use (response = > {const {code, MSG, data} = response.data if (code ! == '00000') {if (code === 'A0230') {// Access_token expired Use refresh_token refresh to obtain access_token const config = response.config if (refreshing == false) { refreshing = true const refreshToken = getRefreshToken() return store.dispatch('user/refreshToken', If ((token) => {config.headers['Authorization'] = 'Bearer '+ token config.baseURL = '' BaseURL waitqueue.foreach (callback => callback(token)) WaitQueue = [] return service(config)}). Catch (() => {// refresh_token also expires, ConfirmButtonText: 'confirmButtonText:' cancelButtonText: 'cancelButtonText:' cancelButtonText: ', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) }).finally(() => { Refreshing = false})} else {// Refreshing token, Return new Promise((resolve => {waitqueue.push ((token) => {waitqueue.push ((token) => {waitqueue.push ((token) => { Config. headers['Authorization'] = 'Bearer '+ token config.baseURL = '' Url contained baseURL resolve (service (config)})}} else {})) Message ({Message: MSG | | 'system error, type:' error 'duration: 5 * 1000 }) } } return {code, msg, data} }, error => { return Promise.reject(error) } )Copy the code

Test four.

After completing the front and back end code adjustments above, proceed to the test. Remember that the access_token aging is 1s and the refresh_token is 120s. Here the access_token is set to 1s, but the age is actually 61s, for reasons discussed below. Testing is divided into three phases based on time:

  1. 0 to 61s: Both tokens are valid. The request process is normal.

  1. 61s to 120s: The access_token expires. If the access_token expires again, a refresh request will be executed.



  1. 120S + : refresh_token expires.

5. The question

Note: The problem is based on the nimbus-Jose-jwt library used by the Youlai-Mall project and relies on the spring-security-oAuth2-Jose JAR package.

1. How to determine JWT expired?

The final endpoint of JWT expiration is the JwtTimestampValidator#validate method

2. Why is the validity of access_token 60 seconds longer than the setting?

Hanging them? With the background? Borrow another 60 seconds from heaven?

At the beginning, I thought I had made a configuration mistake without knowing it. I set 5s expiration and waited for more than 1min. Finally, I found the JWT validation method JwtTimestampValidator#validate

The basic requirement for JWT is: Instant. Now (this.clock).minus(this.clockskew).isafter (expiry

Expiry = now > expiry + 60s

According to normal understanding, if the current time is greater than the expiration time, it can be judged as expired. But here, a clock offset 60s is added to the expiration time, which is vividly extended by one minute. Why? Did not find the documentation, notes also did not explain, know friends welcome to leave a message below ~

6. Summary

This paper describes how the Youlai-Mall project achieves the functional requirements of JWT renewal through the combination of the front end and the back end with double token refresh. The back end throws token expiration exception, and the front end invokes token refresh request after capturing, and the renewal is completed upon success. Failure (typically when refresh_token is also expired) requires a re-login. During the implementation of the code, you learned how the resource server (Youlai-gateway) determines whether the JWT is expired, how AXIos retries the request, and so on.

Finally, I would like to talk about my own project, which is youlai-Mall integration of the current mainstream development mode, microservice plus front-end and back-end separation. The latest mainstream technology stack Spring Cloud + Spring Cloud Alibaba + Vue, and the most popular unified authentication and authorization Spring Cloud Gateway + Spring Security OAuth2 + JWT. So please keep an eye out if you find this article helpful. Or give a STAR if you are interested in this project. I also look forward to your participation and suggestions. Please feel free to contact me if you have any questions as usual ~ (wechat: HaoxianRUI).

The project name address
The background youlai-mall
Management of the front youlai-mall-admin
Wechat applets youlai-mall-weapp