JWT
JWT(JSON Web Token) is an open jSON-based standard implemented to pass declarations between network application environments.
Example Login Procedure
Here is a personal collation of some information, the need of friends can be directly click to receive.
Java Basics
22 Java Architect Core books
Learning routes and materials from 0 to 1Java
1000+ questions from 2021
composition
What exactly does a JWT look like? JWT is made up of three pieces of information. Use these three pieces of information text. The links together make up the JWT string. Something like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cB ab30RMHrHDcEfxjoYZgeFONFh7HgQCopy the code
The element
header
The header of the JWT carries two pieces of information:
- Declare type, in this case JWT;
- Declare the encryption algorithm, usually directly use HMAC SHA256;
- The complete header looks like this JSON:
{
'typ': 'JWT',
'alg': 'HS256'
}
Copy the code
Using Base64 encryption forms the first part.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
Copy the code
Playload (emphasis)
Payload is the place where valid information is stored, and this valid information consists of three parts:
- A declaration of registration in the standard;
- A public statement;
- A private declaration;
The declaration of registration in the standard (recommended but not mandatory) includes the following parts:
- Iss: JWT issuer;
- Sub: the user JWT is targeting;
- Aud: the side receiving JWT;
- Exp: expiration time of JWT. This expiration time must be longer than the issue time.
- NBF: defines the time before the JWT is unavailable;
- Iat: issue time of JWT;
- The unique identifier of JWT is mainly used as a one-time token to avoid replay attacks.
Public declaration part: Public declaration part can add any information, generally add user information or other necessary information required by the business, but it is not recommended to add sensitive information, because this part can be decrypted on the client.
Private declaration part: A private declaration is a declaration defined by both the provider and the consumer. It is generally not recommended to store sensitive information because Base64 is symmetrically decrypted, which means that this part of the information can be classified as plaintext information.
Define a payload:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Copy the code
It is then base64 encrypted to get the second part of Jwt:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Copy the code
signature
The third part of the JWT is a visa information, which consists of three parts:
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); Var signature = HMACSHA256(encodedString, 'key '); After encryption, the signature information is obtained. TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQCopy the code
JWT final format
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cB ab30RMHrHDcEfxjoYZgeFONFh7HgQCopy the code
Secret is used for JWT signing and JWT validation, so it should not be revealed in any scenario.
The element
SpringBoot integration with JWT
Introduction of depend on
<! --token--> <! Java - JWT </artifactId> </dependency> JWT </artifactId>Copy the code
Create the JWT utility class
Note the configuration file injection for static properties:
package com.neuq.common.util; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.TokenExpiredException; import com.neuq.common.exception.ApiException; import com.neuq.common.response.ResultInfo; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Date; /** * @Author: xiang * @Date: 2021/5/11 21:11 * <p> * JwtToken Generated tool class * JWT token format: header.paypay. signature * Header format (algorithm, token type). Default: {"alg": "HS512","typ": "JWT"} * payload = "payload" * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) */ @Component @configurationProperties (prefix = "JWT ") public class JWTUtils {// Define the token return header public static String header; // Token prefix public static String tokenPrefix; Public static String secret; Public static long expireTime; Public static final String USER_LOGIN_TOKEN = "USER_LOGIN_TOKEN"; public static final String USER_LOGIN_TOKEN = "USER_LOGIN_TOKEN"; public void setHeader(String header) { JWTUtils.header = header; } public void setTokenPrefix(String tokenPrefix) { JWTUtils.tokenPrefix = tokenPrefix; } public void setSecret(String secret) { JWTUtils.secret = secret; } public void setExpireTime(int expireTimeInt) { JWTUtils.expireTime = expireTimeInt*1000L*60; } /** * createToken * @param sub * @return */ public static String createToken(String sub){return tokenPrefix + JWT.create() .withSubject(sub) .withExpiresAt(new Date(System.currentTimeMillis() + expireTime)) .sign(Algorithm.HMAC512(secret)); } /** * public static String validateToken(String token){try {return JWT.require(Algorithm.HMAC512(secret)) .build() .verify(token.replace(tokenPrefix, "")) .getSubject(); } catch (TokenExpiredException e){throw new ApiException(resultInfo. unauthorized(" Token has expired ")); } catch (Exception e){throw new ApiException(resultInfo. unauthorized(" Token authentication failed ")); Public static Boolean isNeedUpdate(String token){// Obtain the token expiration Date expiresAt = null; try { expiresAt = JWT.require(Algorithm.HMAC512(secret)) .build() .verify(token.replace(tokenPrefix, "")) .getExpiresAt(); } catch (TokenExpiredException e){ return true; } catch (Exception e){throw new ApiException(resultInfo. unauthorized(" Token authentication failed ")); Return (expiresat.getTime () -system.currentTimemillis ()) < (expireTime>>1); }}Copy the code
Yaml attribute configuration
JWT: header: "Authorization" #token return header tokenPrefix: "Bearer "#token prefix secret:" qWERtyuiop7418520 "# key expireTime: 1 # Token validity period (minutes) More than one hour is recommendedCopy the code
Login method Returns user information saved in token
@ Override public Map < String, Object > login User (User) {/ / phone is the only sign except the id Need to check the if (user getPhone () = = null | | User.getphone ().equals("")) throw new ApiException(" phone number is invalid "); User selectUser = userDao.selectUserByPhone(user.getPhone()); If (selectUser == null) {// Register user int count = userdao.insertUser (user); If (count < 1) throw new ApiException (ResultInfo. ServiceUnavailable (" registered exception ")); } String token = jwTutils.createToken (selectUser.getUserId().toString()); Map<String,Object> map = new HashMap<>(); map.put("user",selectUser); map.put("token",token); return map; }Copy the code
Note that the token is saved to Http headers
@GetMapping("/login") public ResultInfo login(User user, HttpServletResponse response) { Map<String, Object> map = userService.login(user); Responsetheader (jwtutils.user_login_token, (String) map.get("token")); response.setheader (jwtutils.user_login_token, (String) map.get("token")); response.setheader (jwtutils.user_login_token, (String) map.get("token")); return ResultInfo.success((User)map.get("user")); }Copy the code
The interceptor validates the token on each request
/** * @Author: xiang * @Date: 2021/5/7 20:56 * <p> * Interceptor: */ public class UserLoginInterceptor implements HandlerInterceptor {@override public Boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object Handler) throws Exception {// Obtain the token in the HTTP header. String Token = Request.getheader (jwtutils.user_login_token); / / token does not exist the if (token = = null | | token. Equals (" ")) throw new ApiException (" please login first "); // validateToken String sub = jwtutils.validatetoken (token); If (sub = = null | | sub. Equals (" ")) throw new ApiException (ResultInfo. Unauthorized (" token authentication failed ")); If (jwtutils.isNEEDupDate (token)){String newToken = jwtutils.createToken (sub); String newToken = jwtutils.createToken (sub); response.setHeader(JWTUtils.USER_LOGIN_TOKEN,newToken); } return true; }}Copy the code
@configuration@ComponentScan (basePackages = "com.neuq.mon ") // Global exception handling classes need to be scanned to public class WebMvcConfig implements WebMvcConfigurer {/** * register custom interceptor ** @param registry */ @override public void addInterceptors(InterceptorRegistry) registry) { registry.addInterceptor(new UserLoginInterceptor()) .addPathPatterns("/user/**") .addPathPatterns("/userInfo/**") .excludePathPatterns("/user/login"); // Open the login path}}Copy the code
Single sign-on (sso)
Store token or a unique identifier UUID= uuid.randomuuid ().tostring () in Cookie (not in Http header) and set path to entire project root path /*; This unique identifier is often cached in the server as key, user information as value!!
The last
Thank you big guy can see the end, think the article is helpful to you remember to like!