In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article analyzes "how to implement SpringBoot Integration JWT". The content is detailed and easy to understand. Friends who are interested in "how to implement SpringBoot Integration JWT" can follow the editor's idea to read it slowly and deeply. I hope it will be helpful to everyone after reading. Let's follow the editor to learn more about "how to implement SpringBoot Integration JWT".
one。 Introduction to JWT
1. What is JWT?
JWT (JSON Web Token) is an open standard based on JSON for passing declarations between network application environments.
It encrypts user information into token, and the server does not save any user information. The server verifies the correctness of the token by using the saved key and passes the verification as long as it is correct; application scenarios such as user login. For more information on JWT, please see github: https://github.com/jwtk/jjwt.
two。 Why use JWT?
With the development of technology and the popularity of distributed web applications, the cost of managing users' login status through session is getting higher and higher, so it has gradually developed into token to do login verification, and then use token to get the cached user information in redis. With the emergence of jwt, the verification method is more simple and convenient, not through redis cache, but directly according to token to retrieve saved user information, and to verify the availability of token. Single sign-on is easier.
3. Comparison between traditional Cookie+Session and JWT
① in the traditional user login authentication, because http is stateless, so it is the way of session. If the user logs in successfully, the server will guarantee a session, of course, the client will give the client a sessionId, and the client will save the sessionId in the cookie, and each request will carry this sessionId.
The mode of cookie+session is usually kept in memory, and the session sharing problem faced by services from single service to multi-service increases with the increase of the number of users. This is not the case with JWT. You only need the server to generate a token, and the client saves the token. Each request carries the token, and the server can authenticate and resolve it.
The ② JWT verification method is more simple and convenient, which does not need to go through the redis cache, but directly retrieves the saved user information according to token, and verifies the availability of token, single sign-on and token.
4. Composition of JWT (3 parts)
The first part is the head (header), the second part we call it the load (payload), and the third part is the signature. For intermediate use. Separate]
A standard JWT generates token in the following format: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI1IiwiaWF0IjoxNTY1NTk3MDUzLCJleHAiOjE1NjU2MDA2NTN9.qesdk6aeFEcNafw5WFm-TwZltGWb1Xs6oBEk5QdaLzlHxDM73IOyeKPF_iN1bLvDAlB7UnSu-Z-Zsgl_dIlPiw
5. JWT verification process and characteristics
Verification process:
① declares the encryption algorithm and constants in the header message, and then converts header to a string using json
② declares the user information in the load, along with some other content; once again, use json to convert the load part into a string
③ uses the encryption algorithm declared in header and the randomly generated secret of each project to encrypt the first step of the string and the second part of the string to generate a new string. The word string is unique.
When decrypting ④, as long as the client initiates a request with JWT, the server directly uses secret for decryption.
Features:
① consists of three parts, each of which carries out string conversion
② decrypts without using the database, only using secret for decryption.
The secret of ③ JWT must not be leaked!
6. Advantages and disadvantages of JWT
Advantages:
1. Good scalability
In the case of distributed deployment of applications, Session needs to do multi-machine data sharing, which can usually be stored in a database or Redis. JWT doesn't need it.
two。 Stateless
JWT does not store any state on the server. One of the principles of RESTful API is stateless, and when a request is made, a response with parameters is always returned with no additional impact. This additional effect is introduced into the authentication status of users, which breaks this principle. In addition, some common information can be stored in the load of JWT, which can be used to exchange information. Using JWT effectively can reduce the number of times that the server queries the database.
Disadvantages:
① security: because JWT's payload is encoded in Base64 and is not encrypted, sensitive data cannot be stored in JWT. The information of Session is stored on the server side, which is relatively more secure.
② performance: JWT is too long. Because it is stateless to use JWT, all the data is put into JWT, and if you have to exchange some data, the load will be even greater. After coding, the JWT is very long, and the limit size of Cookie is generally 4k JWT cookies may not fit, so cookies are generally placed in LocalStorage. And every Http request of the user in the system will carry the JWT in the Header, and the Header of the Http request may be larger than the Body. SessionId is only a very short string, so Http requests using JWT are much more expensive than using Session.
③ one-time: statelessness is a feature of JWT, but it also causes this problem. JWT is one-time. If you want to modify the contents, you must issue a new JWT. That is, the defect is that once issued, the service backend cannot refuse the request to carry the jwt (such as kicking out the user)
(1) cannot be discarded: through the verification mechanism of JWT, it can be seen that once a JWT is issued, it will always be valid until it expires and cannot be abandoned halfway. For example, you store some information in payload, and when the information needs to be updated, re-issue a JWT, but since the old jwt has not expired, you can still log in with the old JWT, then the information that the server gets from the JWT after login is out of date. To solve this problem, we need to deploy additional logic on the server, such as setting up a blacklist so that once a new JWT is issued, the old one is added to the blacklist (such as saving it in redis) to avoid being used again.
(2) Renewal: if you use jwt for session management, the traditional Cookie renewal scheme is generally included in the framework. The Session is valid for 30 minutes. If you have access within 30 minutes, the validity period is refreshed to 30 minutes. By the same token, to change the validity period of a JWT, you need to issue a new JWT. One of the simplest ways is to refresh the JWT with each request, that is, a new JWT is returned for each HTTP request. This method is not only violent and inelegant, but also has to encrypt and decrypt JWT every time, which will bring performance problems. Another way is to set the expiration time separately for each JWT in Redis, refreshing the expiration time of the JWT each time you access it.
You can see that if you want to crack the one-time feature of JWT, you need to store the state of jwt on the server. However, after the introduction of redis, the stateless jwt has been rigidly transformed into stateful, which goes against the original intention of JWT. And this plan is almost the same as Session.
two。 Java implements JWT (SpringBoot integration)
1. Maven dependency and application.yml configuration
Io.jsonwebtoken jjwt 0.7.0 com.auth0 java-jwt 3.4.0server: port: 8080spring: application: name: springboot-jwtconfig: jwt: # encryption key secret: abcdefg1234567 # token valid duration expire: 3600 # header name header: token
two。 Write JwtConfig
Token of package com.example.config; import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.Date; / * JWT, case sensitive * / @ ConfigurationProperties (prefix = "config.jwt") @ Componentpublic class JwtConfig {private String secret; private long expire; private String header / * generate token * @ param subject * @ return * / public String createToken (String subject) {Date nowDate = new Date (); Date expireDate = new Date (nowDate.getTime () + expire * 1000) / / expiration time return Jwts.builder () .setHeaderParam ("typ", "JWT") .setSubject (subject) .setIssuedAt (nowDate) .setExpiration (expireDate) .signWith (SignatureAlgorithm.HS512, secret) .compact () } / * get the registration information in token * @ param token * @ return * / public Claims getTokenClaim (String token) {try {return Jwts.parser (). SetSigningKey (secret) .parseClaimsJws (token). GetBody ();} catch (Exception e) {/ / e.printStackTrace (); return null }} / * verify whether token expires * @ param expirationTime * @ return * / public boolean isTokenExpired (Date expirationTime) {return expirationTime.before (new Date ()) } / * * get token failure time * @ param token * @ return * / public Date getExpirationDateFromToken (String token) {return getTokenClaim (token) .getExpiration ();} / * get the user name from token * / public String getUsernameFromToken (String token) {return getTokenClaim (token) .getSubject () } / * get jwt release time * / public Date getIssuedAtDateFromToken (String token) {return getTokenClaim (token) .getIssuedAt ();} / /-getter & setter-public String getSecret () {return secret } public void setSecret (String secret) {this.secret = secret;} public long getExpire () {return expire;} public void setExpire (long expire) {this.expire = expire;} public String getHeader () {return header;} public void setHeader (String header) {this.header = header;}}
3. Configure interceptor
Package com.example.interceptor; import com.example.config.JwtConfig;import io.jsonwebtoken.Claims;import io.jsonwebtoken.SignatureException;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; @ Componentpublic class TokenInterceptor extends HandlerInterceptorAdapter {@ Resource private JwtConfig jwtConfig @ Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws SignatureException {/ * * address filtering * / String uri = request.getRequestURI (); if (uri.contains ("/ login")) {return true } / * * Token verification * / String token = request.getHeader (jwtConfig.getHeader ()); if (StringUtils.isEmpty (token)) {token = request.getParameter (jwtConfig.getHeader ());} if (StringUtils.isEmpty (token)) {throw new SignatureException (jwtConfig.getHeader () + "cannot be empty");} Claims claims = null Try {claims = jwtConfig.getTokenClaim (token); if (claims = = null | | jwtConfig.isTokenExpired (claims.getExpiration () {throw new SignatureException (jwtConfig.getHeader () + "invalid, please log in again.") ;} catch (Exception e) {throw new SignatureException (jwtConfig.getHeader () + "is invalid, please log in again.") ;} / * * set identityId user identity ID * / request.setAttribute ("identityId", claims.getSubject ()); return true;}}
Register the interceptor to SpringMvc
Package com.example.config; import com.example.interceptor.TokenInterceptor;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource; @ Configurationpublic class WebConfig implements WebMvcConfigurer {@ Resource private TokenInterceptor tokenInterceptor; public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (tokenInterceptor) .addPathPatterns ("/ *");}}
4. Write a unified exception handling class
Package com.example.config;import io.jsonwebtoken.SignatureException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestControllerAdvice;import org.yuyi.full.handler.exception.ExceptionInfoBO;import org.yuyi.full.handler.exception.ResultBO;import org.yuyi.full.handler.exception.ResultTool @ RestControllerAdvicepublic class PermissionHandler {@ ExceptionHandler (value = {SignatureException.class}) @ ResponseBody public ResultBO authorizationException (SignatureException e) {return ResultTool.error (new ExceptionInfoBO (1008 dint. GetMessage ());}}
5. Write a test interface
Package com.example.controller; import com.alibaba.fastjson.JSONObject;import com.example.config.JwtConfig;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.yuyi.full.handler.exception.ResultBO;import org.yuyi.full.handler.exception.ResultTool;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest Import java.util.HashMap;import java.util.Map; @ RestControllerpublic class TokenController {@ Resource private JwtConfig jwtConfig / * param userName * @ param passWord * @ return * / @ PostMapping ("/ login") public ResultBO login (@ RequestParam ("userName") String userName, @ RequestParam ("passWord") String passWord) {JSONObject json = new JSONObject () / * * verify whether the userName,passWord is consistent with the database. If not, directly return ResultTool.errer () [omit this step here] * / / here simulate querying userId from database to String type through user name and password. In actual development, if subject needs to store userId, the parameter of createToken method of JwtConfig can be set to Long type String userId = 5 + "; String token = jwtConfig.createToken (userId) If (! StringUtils.isEmpty (token)) {json.put ("token", token);} return ResultTool.success (json);} / * Interface requiring Token authentication * / @ PostMapping ("/ info") public ResultBO info () {return ResultTool.success ("info") } / * obtain userId * @ param request * @ return * / @ GetMapping ("/ getUserInfo") public ResultBO getUserInfo (HttpServletRequest request) {String usernameFromToken = jwtConfig.getUsernameFromToken (request.getHeader ("token")) according to the token of the request header; return ResultTool.success (usernameFromToken) } / * Why can I still access info and other APIs that require token verification with the previous token after the project is restarted? Answer: as long as it does not expire, it will always exist, similar to redis * /}
Test it with the PostMan test tool. Visit the login interface. When the account password is verified, a token is returned to the client:
When you directly access the info interface, a custom exception with empty token will be returned:
When the correct token is added to the request header, the interceptor verifies that it can access the interface normally:
When an error token is added to the request header, a custom exception with token invalidation will be returned:
Next, test to get the user information. Because the subject stored here is userId, the fake data written above is returned directly:
JWT
1. Based on JSON, JWT can be supported across languages, and many languages such as JAVA,JavaScript,Node.JS,PHP can be used.
2. In the payload part, JWT can store some non-sensitive information necessary for other business logic when needed.
3. Small size, easy to transfer; the composition of JWT is very simple, the byte footprint is very small, so it is very easy to transfer. It does not need to save session information on the server side, so it is easy to apply extensions.
On how to carry out SpringBoot integration JWT implementation to share here, I hope that the above content can make you improve. If you want to learn more knowledge, please pay more attention to the editor's updates. Thank you for following the website!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.