Understand http session
In fact, for a long time, in the interaction between the front and back end, I have been confused about what this http session is. Why is there a request in the input parameter of the controller method to fetch the front end? The parameters passed in are easy to understand, but why is there an httpsession where the data in it comes from, and why is the data set in it?
Scenario one
In order to facilitate understanding of this, let’s take a basic SMS login scenario.
Suppose there is an app, and a user wants to log in to it:
Log in, and then look at your personal page, just 2 steps.
When you log in, the front end sends a request to the back end with your username aaa password 123 and then the login is successful
At this time, you have to click on the personal page,,,,,
stop! The problem here is that the Http protocol has no memory and is stateless. There is no relationship between this request and the previous request. It will not save the process of the previous request. After the request, it will forget the previous request, just like when you talk about a girl, you forget the last girl. Since it forgot, I’m sorry, you are going to click on the personal page now, how do I know that you are just aaa?
There is no way. At this time, the front-end has to pass the user name aaa and password 123 to tell the back-end that I am aaa. After the back-end checks, let you visit the personal page of aaa.
Ok, after reading the personal page, you want to see the personal wallet again. I’m sorry at this time because it’s a request on the http protocol. I’ve forgotten that you want to see the aaa’s personal wallet, so you have to pass the user name and password again, otherwise how can I Know you are aaa?
Very sb right? This is the disaster encountered when the front-end and back-end interactive programs first emerged.
Scene reappearance
At this moment. . . Cookie and session appeared. The former belong to the client, such as the browser or your mobile app. The latter belongs to the server.
How do these two solve the problem of which scenario above:
Suppose there is an app, and a user wants to log in to it:
Log in, and then look at your personal page, just 2 steps.
When you log in, the front end sends a request to the back end with your username aaa password 123 and then the login is successful.
Note that when your request is sent to the backend for the first time, the server tomcat will automatically create a session in the server. You can understand this session as a map, which stores various key-value pairs, one of which is the id Each session has an id. For example, the aaa user requested for the first time to create a session id called 123124314, and then send the session id to the front end and store it in the cookie.
Then the session is always there throughout the session cycle, and the session can be identified by using 123124314 when the front end accesses the back end. After you verify the username and password for the first time, you can store ta in the session with the id of 123124314.
After logging in in the future, you will continue to click on other pages. At this time, you can take out the previously saved data from the session every time for verification.
HTTP has no memory, but part of the memory will be retained through the session.
Use redis instead of session
What’s wrong with session?
It is generated in the tomcat server, but if you practice multiple tomcat servers at the same time. Their respective sessions are not interoperable.
This is very inconvenient.
At this time, redis appeared, which improves a unified area for fast reading. The part that was originally stored in the session can now be stored in redis.
Let’s now talk about how redis implements the function of SMS verification and login:
First, fill in the mobile phone number in the browser and click to send the verification code. This is the first step:
Find a code example:
public Result sendCode(String phone, HttpSession session) {<!-- --> //Verify the mobile phone number //The mobile phone number does not match, return an error message if(RegexUtils.isPhoneInvalid(phone)){<!-- --> return Result.fail("Mobile phone number format error"); } //Conform to generate verification code using treasure chest hutool String code = RandomUtil. randomNumbers(6); //Save to session // session.setAttribute("code",code); //Refactor the code here, change the original save code to the session, and now use redis to store it //In order to make a better distinction, add some prefixes in front of the key here, and add the validity period stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES); //Send Here, use pseudo-send to type the verification code into the log log.debug("Send verification code successfully Verification code:{}",code); // return the result object return Result.ok(); }
First send the verification code. After sending the verification code, the back end needs to find a place to save it and it is time-sensitive. When the verification code and the mobile phone number are sent by the front end, the verification codes on both sides are compared to determine whether the user has successfully logged in. So we put the verification code The key is the prefix_phone value and the verification code is stored in redis
User login
After the user receives the verification code, he will log in with the verification code and mobile phone number.
At this time, our first step is to verify whether the verification codes on both sides are correct.
If it is correct, we have to verify whether this is a new user, if it is, create a user and store it in the database table, if not, take the user’s information from the database.
Save this information in redis, and then every time you want to log in for verification, take the user from the original session to prove that you are aaa, and then take it from redis.
There is another point to note here. In the past, the session server automatically created the id. The browser will bring the id to find the session. Now it is replaced with a map in redis. You need to set a token so that the front end will use this token every time it visits It is a good choice to bring it, such as putting it in the header of the request.
In redis, it is the relationship of
Let’s take a simple code example
public Result login(LoginFormDTO loginForm, HttpSession session) {<!-- --> //The user has received the verification code sent, now submit the mobile phone number and verification code //Check phone number String phone = loginForm. getPhone(); if(RegexUtils.isPhoneInvalid(phone)){<!-- --> return Result.fail("Mobile phone number format error"); } //Check whether the verification code is the same as that in redis Object cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone); String code = loginForm. getCode(); if(cacheCode == null || !cacheCode.toString().equals(code)){<!-- --> //The verification is inconsistent, and an error is reported directly return Result.fail("The verification code is wrong or the verification code has expired"); } // Get the user object from the database User user = query().eq("phone",loginForm.getPhone()).one(); //Check if the user exists if (user==null){<!-- --> user = createUserWithPhone(loginForm. getPhone()); } //Randomly generate a token as the key of the user object String token = UUID.fastUUID().toString(true); UserDTO userDTO = BeanUtil. copyProperties(user, UserDTO. class); //Convert the user object into a map //Note that there is a pit in this place because stringRedisTemplate is used and all basic data types need to be string structures. Map<String,Object>userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(), CopyOptions. create() .setIgnoreNullValue(true) .setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString())); String tokenKey = LOGIN_USER_KEY + token; stringRedisTemplate.opsForHash().putAll(tokenKey,userMap); // Set the validity period separately stringRedisTemplate.expire(token,LOGIN_USER_TTL,TimeUnit.MINUTES); return Result.ok(token); }
Finally, what is the most important role of redis in this function?
That’s right, it replaces the original session’s function of temporarily storing data. Pay attention to this temporary, persistent data we store in mysql and other temporary data with a relatively short life cycle, we store it in redis and add timeliness.