Abstract: This paper mainly studies the sharing problem of distributed session based on Spring-Seesion. Firstly, I will talk about the functions and working principles of session and cookie. Then, I will step into the topic and describe the background of session sharing problems and common solutions. Then we introduce two ways to manage the sessionID of Spring-Session and the corresponding usage scenarios. Then the data structure of the background data saved to Redis is analyzed. Then the core source code of Spring-Session is read to facilitate the understanding of the implementation principle of the Spring-Session framework.
Session and Cookie
1.Cookie:
Because the HTTP protocol is stateless, that is, the server does not know what the user did last time and cannot create a correlation with the same user request, the browser needs to provide a mechanism for the server to recognize, which is when cookies appear. Cookie and session mechanisms are introduced to maintain state information. When the user accesses the server for the first time, the server responds with a set-cookie header. In this case, a Cookie is Set locally. When the user accesses the server again, HTTP will send the Cookie. There’s a sessionId in the cookie and it goes to the server to make sure it’s the same session.
Cookie attributes:
Name: Indicates the name of the cookie. Once the cookie is created, the name cannot be changed
Value: the cookie value
Comment: Description of the Cookie’s usefulness. This description is displayed when the browser displays Cookie information.
Domain: indicates the domain name that can access the Cookie. If the Cookie is set to.baidu.com, all domain names ending in baidu.com can access the Cookie. That is, the same cookie can be accessed only if the first-level domain names are the same.
MaxAge: indicates the Cookie expiration time, in seconds.
If the value is positive, the value expires after maxAge seconds. If the value is negative, the Cookie is a temporary Cookie. The Cookie will become invalid when the browser is closed and the browser will not save the Cookie in any form. If the value is 0, the Cookie is deleted. Path: indicates the usage path of the Cookie. Such as:
Path =/, indicating that the Cookie can be accessed by contextPath in the domain name.
Path =/app/, only the programs with contextPath set to /app can access the Cookie.
When path is set, it ends with a slash.
Secure: Indicates whether the Cookie is transmitted only using the security protocol. The security protocols include HTTPS and SSL. The default is false.
Cookies do not support cross-domain. For cookies, the same origin of cookies only focuses on domain names, ignoring protocols and ports. So in general, the cookies of https://localhost:80/ and http://localhost:8080/ are shared.
Cookies are not cross-domain; In the absence of any processing, the secondary domain name is not the same. (wenku.baidu.com and baike.baidu.com). The same cookie can be accessed only when domainName is set to. Baidu.com.
Cookie number & size restrictions and handling strategy www.cnblogs.com/henryhappie…
2.Session
Cookie makes up for the stateless HTTP protocol. Before sessions, almost all websites used cookies to track sessions. Unlike cookies, sessions store state on the server.
When a client requests to create a session, the server first checks whether the request contains a session id – sessionId.
If the sessionId is already included, a session has already been created for the client. The server retrievals the session based on the sessionId and uses it (if not, a new session may be created). A session is created for this client and a sessionId associated with this session is generated
The value of the sessionId is usually a string that is neither duplicated nor easily counterfeited. The sessionId will be returned to the client for storage in this response. The way to save the sessionId is mostly using cookies.
Extension: The lifetime of the session
Session creation: When resquest's getSession method is used for the first time, the Web server creates a session using: After the session is created on the server, the memory will allocate a certain space for the session and generate a temporary cookie and return it to the user. The browser creates cookies through set-cookie and saves them locally. The subsequent access will find the corresponding session through this cookieID. Session destruction: 1. Default destruction: If there is no interaction with the server within 30 minutes, the session is destroyed by default. 2. Manual destruction: The session is destroyed when the session invalidate method is called. 3. Shut down the server: memory space is reclaimed, so there is no session.Copy the code
Solution -SpringSession
Httpsessions are created and managed by Servlet containers, and things like Tomcat/Jetty are kept in memory. If we build a distributed cluster of Web servers and use Nginx for load balancing, Http requests from the same user may be distributed to two different Web sites. So how do you ensure that different Web sites can share the same session data?
The simplest way to do this is to pull the session out of the container. The first is to use container extensions. The more acceptable ones are container plug-ins, such as tomcat-redis-session-manager based on Tomcat, jetty-session-redis based on Jetty, and so on. The benefit is that it is transparent to the project and no code changes are required. The former, however, does not yet support Tomcat 8, or is not fully developed. But because of the dependency on containers, upgrading or replacing containers means starting all over again. And the code is not in the project and maintenance is a problem for developers.
The second is to write a set of tool classes for Session management, including Session management and Cookie management, which can be obtained from their own tool classes when they need to use sessions, and the back-end storage of tool classes can be put into Redis. This is obviously the most flexible solution, but it will take some extra time to develop. In addition, there are two sets of Session schemes in the system, so it is easy to make a mistake and fail to get data.
The third is to use the framework’s session management tool, spring-Session, which replaces the Servlet set of session management and takes over the task of creating and managing session data. No container dependencies, no code changes, and spring-data-Redis connection pooling is the perfect solution. In addition to redis managed storage, spring-Sessions can also be stored via JDBC via a database
1. Spring Session provides apis and implementations for managing user Session information. In addition, it provides the following features:
2. Offload the state held by the session to a specific external session store summary, such as Redis, which can provide a high quality cluster independent of the application server.
3. Control how session ids are exchanged between clients and servers so that iT is easy to write Restful apis that get session ids from HTTP headers instead of relying on cookies.
4. Access to session data in non-Web request processing code, such as JMS message processing code.
Support multiple sessions per browser, making it easy to build a richer end-user experience.
The HttpSession can be kept active while the user sends a request using WebSocket.
Solution 1: manage sessionid by cookie (default management mode) it is very easy to integrate springsession in springboot
Since spring-Session adopts the cookie management policy by default, you only need to add the @enableredisHttpSession annotation in the startup class to use spring-Session. The parameter corresponding to the session expiration time and redis storage space can be set. Refresh mode and periodic cleanup. MaxInactiveIntervalInSeconds – the session expires after a few seconds of time
RedisNamespace – Allows you to configure application-specific namespaces for sessions. The Redis key and channel ID will start with the spring: Session :: prefix.
RedisFlushMode – Allows you to specify when data is written to Redis. The default value is only used when calling Save on SessionRepository. The value RedisFlushMode.IMMEDIATE is written to Redis as soon as possible.
SpringSession provides the default implementation of DefaultCookieSerializer interface. Of course, in practical applications, we can also implement this interface ourselves. Then through CookieHttpSessionIdResolver# setCookieSerializer (CookieSerializer) method to specify our own way.
Solution 2: Use HttpHeader to manage session ids
Spring-session supports request headers to manage sessions. When cookies are disabled, the request headers can carry tokens to match corresponding sessions. Spring Session allows you to provide Session ids in Headers to use RESTful APIs
Here is how to use these two management methods: the policy for resolving the sessionId in SpringSession is represented by the HttpSessionIdResolver interface. HttpSessionIdResolver has two implementation classes:
List<String> resolveSessionIds(HttpServletRequest request);
void setSessionId(HttpServletRequest request, HttpServletResponse response,String sessionId);
void expireSession(HttpServletRequest request, HttpServletResponse response);
Copy the code
}
ResolveSessionIds: Resolves the session ids associated with the current request. The sessionId may come from a Cookie or request header.
SetSessionId: sends the given sessionId to the client. This method is called when a new session is created and tells the client what the new session ID is.
ExpireSession: instructs the client to end the current session. This method is called when a session is invalid and the client should be notified that the sessionId is no longer valid. For example, it might delete a Cookie that contains a sessionId, or set an HTTP response header whose value is null to indicate that the client does not submit the sessionId again.
We can choose the appropriate session management strategy by creating a custom implementation class of HttpSessionIdResolver.
SpringSession source code parsing
Here is spring – the session management by redis, if you need to understand how to operate the redis is, you need to understand the RedisOperationsSessionRepository this class.
RedisOperationsSessionRepository is using Spring Data RedisOperations SessionRepository implementation. In a Web environment, this is often used in conjunction with SessionRepositoryFilter. This implementation supports SessionDestroyedEvent and SessionCreatedEvent to SessionMessageListener.
The most basic API for using Sessions in Spring Sessions is SessionRepository. The API is intentionally simple, so it’s easy to provide other implementations with basic functionality. Some can also choose to implement FindByIndexNameSessionRepository SessionRepository implementation. For example, the Spring FindByIndexNameSessionRepository Redis support implementation. FindByIndexNameSessionRepository added a way to find a particular all of the user’s session. This is used by ensuring that the user name fill name for FindByIndexNameSessionRepository. PRINCIPAL_NAME_INDEX_NAME session attributes. It is the developer’s responsibility to ensure that the properties are populated because Spring Session is unaware of the authentication mechanism being used. Here’s an example of how to use it:
String username = “username”; this.session.setAttribute( FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username); Certain FindByIndexNameSessionRepository implementation will provide hooks to automatic indexing other session attributes. For, for example, many implementation will automatically ensure that use the index name FindByIndexNameSessionRepository. PRINCIPAL_NAME_INDEX_NAME index of the current Spring Security user name.
String username = "username";
Map<String, Session> sessionIdToSession = this.sessionRepository .findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,username);