preface
This blog post focuses on the realization of functional requirements. There are not many conceptual things, so if you want to know more about a more comprehensive JWT or want to know the implementation principle of single sign on and others, you can move to other blogs. Here, the blogger has read two blogs casually
-
JWT
- https://www.jianshu.com/p/abddaae52429
- https://www.jianshu.com/p/344a3d5bbab6
-
Single sign on
- https://zhuanlan.zhihu.com/p/97301347
- https://blog.csdn.net/IT_10000/article/details/80634471
- https://www.cnblogs.com/suim1218/p/7699041.html
Requirements design ideas
-
When the user logs in, the front end – > the back end transmits data (id,name,password, etc.), and the password stored in the database may be encrypted, so the password transmitted from the front end should also be encrypted
-
select in the database. If it exists, a token is generated at the back end and returned to the front end. If it does not exist, the response user or password is wrong
Structural composition of JWT
-
Header header
- Token type and encryption algorithm. Common encryption algorithms include MD5, SHA and HMAC (Hash Message Authentication Code)
-
PayLoad load:
-
Store valid information
-
Label declaration
- ISS (issuer) -- issuer
- Subject – subject oriented
- aud Audience – recipient
- exp Expiration time – expiration time stamp
- nbf Not Before – effective time stamp
- iat(Issued at) – date of issue
- jti (JWT ID) – unique identification
-
Public statement
- Generally, necessary information related to business is added, because it can be decrypted, and sensitive information is not recommended.
-
Private declaration
- The declaration jointly defined by the provider and the consumer is decrypted symmetrically by Base64, and sensitive information is not recommended
-
-
-
Signature visa:
- Base64 encrypted header
- Base64 encrypted payload
- secret key
- The encryption algorithm declared in the header is used to encrypt the encrypted strings of header and payload with salt and secret combination. The key is saved in the server, and the server decrypts and verifies according to the key
development tool
Idea + Maven + postman (front end test)
development environment
SpringBoot + Maven
jar package
<!-- Cross domain authentication solution Json web token package--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency>
Develop JWT tool classes
Value transfer: user (user information)
import com.maoni.maoni_xdclass.model.entity.User; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; /** * Jwt Tool class * Note: * 1,The generated token can decrypt plaintext information through base64 * 2,base64 Decrypt the plaintext information, modify it, and then encode it. Decryption fails * 3,The issued token cannot be invalidated unless the secret key is changed */ public class JWTUtils { /** * Expiration time, one week */ private static final long EXPIRE = 60000 * 60 * 24 * 7; /** * Encryption key, custom string */ private static final String SECRET = "*******"; /** * Token prefix, custom string */ private static final String TOKEN_PREFIX = ""*******";"; /** * Face response body, custom string */ private static final String SUBJECT = ""*******";"; /** * Generate token according to user information * @param user * @return */ public static String genJsonWebToken(User user){ String token = Jwts.builder().setSubject(SUBJECT) .claim("head_img",user.getHeadImg()) .claim("id",user.getId()) .claim("name",user.getName()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) .signWith(SignatureAlgorithm.HS256,SECRET).compact(); token = TOKEN_PREFIX + token; return token; } /** * Method of verifying token * @param token * @return */ public static Claims checkJWT(String token){ try{ final Claims claims = Jwts.parser().setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX,"")).getBody(); return claims; }catch (Exception e){ return null; } } }
Test util utility class
Test function 1:Login
- According to the actual business requirements, the user login is realized. If the user logs in successfully, a token is returned. If it fails, the user is reminded that the entered user name or password is wrong
service
/** * register * @param root * @param pwd * @return */ String login(String root, String pwd);
impl
/** * Sign in * @param phone * @param pwd * @return */ @Override public String login(String phone, String pwd) { //The password value is returned according to the user value query table transmitted from the front end User user= userMapper.login(phone,CommonUtils.MD5(pwd)); if (user != null){ //Generate a token and send it to the front end for saving String token = JWTUtils.genJsonWebToken(user); return token; }else { return null; } }
controller
/** * User login interface development * @param loginRequest * @return */ @RequestMapping("login") public JsonData login(@RequestBody LoginRequest loginRequest){ //Log in for verification, and a token is generated after successful verification String token = userService.login(loginRequest.getPhone(),loginRequest.getPwd()); return token ==null?JsonData.buildError("Wrong account or password,Please log in again"):JsonData.buildSuccess(token); }
Test function 2:select_by_token
- Query the user's personal information through the token value transmitted from the front end
- The focus here is on the token value transmitted from the front end. The back end decrypts to obtain the user id or user name, and queries the user information according to these conditions (occurring in the controller)
service
/** * Query user information * @param userId * @return */ User findByUserId(Integer userId);
impl
/** * According to the token transmitted by the front end, obtain the personal id and query the personal information * @param userId * @return */ @Override public User findByUserId(Integer userId) { return userMapper.findByUserId(userId); }
controller
/** * According to the token transmitted by the front end, obtain the personal id and query the personal information */ @RequestMapping("find_by_token") public JsonData findByUserToken(HttpServletRequest request){ Integer userId = (Integer)request.getAttribute("user_id"); if(userId ==null){ return JsonData.buildError("Query failed"); } User user =userService.findByUserId(userId); return JsonData.buildSuccess(user); }
reflection???
- Why does the front end need to use HttpServletRequest request to accept the request object when sending a request???
- Also, why can I directly take "user_id" from the request field?
Tip: what you are thinking about involves the concept of interceptor. All unsolicited requests go through the interceptor. After the request is sent to the server, the interceptor intercepts, processes the data, parses and generates the data required by the controller layer. Therefore, here, the interceptor has decrypted the token and put the user id or user information into the request
Later, you may write another article about the implementation function of the interceptor... It seems relatively simple, because the blogger is a rookie, so the blog can make do with it. If there is anything wrong, please point out. Thank you