Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to customize key and expiration time in spring-redis-session

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces how to customize key and expiration time in spring-redis-session, which can be used for reference by interested friends. I hope you can learn a lot after reading this article.

For distributed applications, the first problem encountered is the storage of session. The solutions are roughly as follows

Using spring-session, it can store session in the location you want to store. For example, redis,mysql uses JWTs, which uses algorithms to verify whether the token is valid and expired, and the token cannot be forged and the information cannot be tampered with.

The main content of this article is that spring-session uses redis to store session, implementation principle, modify expiration time, custom key and so on.

Spring-session is OK for internal systems and easy to use, but if the number of users comes up, it will make redis have a lot of session storage overhead, which is not very cost-effective.

Use

It is relatively easy to use, to put it simply, to introduce the package, configure and annotate it. As shown in the following three steps, you are ready to use redis-session.

Org.springframework.boot spring-boot-starter-data-redis org.springframework.session spring-session-data-redis

Spring.redis.host=localhost # find other timeouts, ports, libraries, connection pools, clusters, etc.

@ EnableRedisHttpSession (maxInactiveIntervalInSeconds= 1800)

Test: because the Session is created during getSession, we have to call it once in the interface to see the effect

GetMapping ("/ sessionId") public String sessionId () {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes ()) .getRequest (); HttpSession session = request.getSession (); session.setAttribute ("user", "sanri"); return session.getId ();}

Its storage results are as follows

Hash spring:session:sessions:e3d4d84f-cc9f-44d5-9199-463cd9de8272string spring:session:sessions:expires:e3d4d84f-cc9f-44d5-9199-463cd9de8272set spring:session:expirations:1577615340000 the first hash structure stores some basic information of session and some attribute information set by users.

CreationTime creation time

Last visit time of lastAccessedTime

The expiration time of maxInactiveInterval. The default is 30 minutes. The second value saved here

SessionAttr:user, this is the property I set through session.setAttribute.

The second string structure, which has no value, only has a ttl message, indicating how long this group of key can live, which can be viewed with ttl.

The third set structure, which stores the key that needs to expire

Realization principle

Explanation: this implementation is not very difficult, I just read it according to the source code, it is just an application of a filter.

First of all, I learned from the Internet that it uses filters to store session to redis, and then every request gets session from redis, so the goal is to see which filter is, how it is stored, and how it is obtained.

We can enter and view it from its only entry @ EnableRedisHttpSession, which introduces a RedisHttpSessionConfiguration to start a timer, which inherits from SpringHttpSessionConfiguration, and you can notice that RedisHttpSessionConfiguration creates a Bean RedisOperationsSessionRepository repository which means a repository, so it is the core class to store the session. Where is the filter? check out SpringHttpSessionConfiguration, which belongs to the spring-session-core package. This is a package used by spring to manage session. It is an abstract concept. The specific implementation is completed by spring-session-data-redis. The filter must be created here. Sure enough, you can see that it creates a SessionRepositoryFilter filter. Let's look at the filter and storage respectively.

SessionRepositoryFilter

The filter must have a doFilter method. Check the doFilter method. Spring wraps the doFilter with OncePerRequestFilter, and finally calls doFilterInternal. Check the doFilterInternal method.

The implementation method is to use the wrapper design to wrap the request and response responses. We usually take the session from request.getSession (), so the packaged request must rewrite the getSession, so we can see how to get the session from the redis by using the getSession method.

All the previous session judgments are relevant, and the key information is here.

S session = SessionRepositoryFilter.this.sessionRepository.createSession ()

SessionRepository here is the RedisOperationsSessionRepository view createSession method that we use to access session.

RedisOperationsSessionRepository

/ / the data that can be seen in the hash structure in redis RedisSession redisSession = new RedisSession (); this (new MapSession ()); this.delta.put (CREATION_TIME_ATTR, getCreationTime (). ToEpochMilli ()); this.delta.put (MAX_INACTIVE_ATTR, (int) getMaxInactiveInterval (). GetSeconds ()); this.delta.put (LAST_ACCESSED_ATTR, getLastAccessedTime (). ToEpochMilli ()); this.isNew = true;this.flushImmediateIfNecessary ()

In the flushImmediateIfNecessary method, if redisFlushMode is in IMMEDIATE mode, session will be saved into redis immediately, but ON_SAVE is configured by default, so where is it saved into redis? let's go back to the original filter doFilterInternal method, and there is a sentence in finally

WrappedRequest.commitSession ()

This is where the session is stored in the redis. Let's go in and have a look. The core statement is this sentence.

SessionRepositoryFilter.this.sessionRepository.save (session)

Session.saveDelta (); if (session.isNew ()) {String sessionCreatedKey = getSessionCreatedChannel (session.getId ()); this.sessionRedisOperations.convertAndSend (sessionCreatedKey, session.delta); session.setNew (false);}

Enter saveDelta, where the hash structure is set

GetSessionBoundHashOperations (sessionId) .putAll (this.delta)

The last line sets the expiration time and adds the current key to the set, which readers can see for themselves.

RedisOperationsSessionRepository.this.expirationPolicy .onExpirationUpdated (originalExpiration, this)

Modify some parameters

In actual business, some parameters may need to be modified to meet the requirements of our business. The most common requirement is to modify the expiration time of session. Some basic configurations have been provided in the EnableRedisHttpSession notes, such as

The maximum expiration time of maxInactiveIntervalInSeconds. The default is 30 minutes when redisNamespace is inserted into the session namespace of redis. The default is spring:session cleanupCron expired session cleaning task, and the default is one minute clean up redisFlushMode refresh method. In fact, it is used in the flushImmediateIfNecessary method of the above principle. The default is that ON_SAVEredisNamespace must be modified. This modification will not affect other projects. Generally, we use the name of our project plus the keyword session to do key, indicating that this is the session information of this project.

However, this configuration is obviously not enough, for the maximum expiration time, it may need to be added to the configuration file rather than written in the code, but the placeholder function is not provided here. Back to the creation of RedisOperationsSessionRepository, the final configured maxInactiveIntervalInSeconds has to be set to this bean. We can override the creation process of this bean and rewrite the acquisition process of maxInactiveIntervalInSeconds. The code is as follows.

@ AutowiredRedisTemplate sessionRedisTemplate;@AutowiredApplicationEventPublisher applicationEventPublisher;@Value ("${server.session.timeout}") private int sessionTimeout = 1800 leading Primary / / use Primary to override the default Bean @ Beanpublic RedisOperationsSessionRepository sessionRepository () {RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository (sessionRedisTemplate); / / to reference the original attribute here to avoid errors, you can reference the original class and copy the attribute; copy the return sessionRepository;} like redisNamespace,redisFlushMode

There is also the problem of serialization of redis. By default, object serialization of jdk is used. It is easy to add a field or decrease a field that cannot be deserialized, so the serialization method needs to be changed. If the cache in the project already uses object serialization, write a separate redisTemplate for it and set it into it, and set redisTemplate when building RedisOperationsSessionRepository

Another is that the key values generated in redis are all in the form of uuid, so there is no way to know which user logged in to the current key. In fact, we can change its key to userId_ip_time to indicate when the user has logged in to which ip. This is how I played it (not used in practice, although it can be changed, but there may be holes):

After the previous source code analysis, it is RedisOperationsSessionRepository's createSession method that creates session and saves it to redis, but it is written here that RedisSession uses empty construction, and RedisSession is the inner class of final, access permission is default, and new MapSession is also default when construction. in the end, that id is to use UUID, which seems to have no way at all. in fact, after creating a session here, the user may not be logged in successfully. We should modify the key of session only after logging in successfully. Fortunately, RedisOperationsSessionRepository provides a method findById. We can make an article on this, first check out RedisSession, and then use reflection to get MapSession, and then notice that MapSession can modify id. It also provides the method changeSessionId. We can call setId to modify sessionId after logging in successfully, and then write it back. The code must be in the same package as RedisSession:

Package org.springframework.session.data.redis;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.session.MapSession;import org.springframework.stereotype.Component;import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;@Componentpublic class SessionOperation {@ Autowired private RedisOperationsSessionRepository redisOperationsSessionRepository; public void loginSuccess (String userId) {String sessionId = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes ()) .getRequest () .getSession () .getId (); RedisOperationsSessionRepository.RedisSession redisSession = redisOperationsSessionRepository.findById (sessionId) Field cached = ReflectionUtils.findField (RedisOperationsSessionRepository.RedisSession.class, "cached"); ReflectionUtils.makeAccessible (cached); MapSession mapSession = (MapSession) ReflectionUtils.getField (cached, redisSession); mapSession.setId ("userId:1"); redisOperationsSessionRepository.save (redisSession);}}

Thank you for reading this article carefully. I hope the article "how to customize key and expiration time in spring-redis-session" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report