javaweb中我们项目稍微正规点,都会用到单点登录这个技术。实现它的方法各家有各界的看法。这几天由于公司项目需求正在研究。下面整理一下最近整理的心得。
Brief introduction
- Another headache in distributed projects is the sharing of data between multiple projects (i.e. session sharing), where data loss often occurs. In order to resolve this bug. Our predecessors have achieved two solutions. Today I'm here for a little bit of these two ways. Focus on the second method of bias
With Tomcat to achieve session sharing resources download
Click I download
Configure Tomcat
<Valve classname = " Com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve "/> manager classname = "Com.orangefunction.tomcat.redissessions.RedisSessionManager" host = port = "7006" database = "db0" maxinactiveinterval = "" "/>
The host and port configured above are our Redis host and port, so we need to start a Redis service before this.
Point me to see how to configure Redis (this article configures the cluster as a single node)
Point I see how to configure Redis and spring consolidation
Point I see how to configure a rollup of issues that you encounter in Redis
Database is the location of the session that is generated when the Tomcat and the browser session are stored in Redis
- Maxinactiveinterval is setting the cache expiration time. But in the actual test I found that this attribute did not work. (What do you have in your opinion welcome reviews)
Here our first Tomcat configuration is complete. Here's how to repeat the above steps to configure several Tomcat
Configure Nginx
- Nginx features rich, can be used as an HTTP server, or as a reverse proxy server, mail server. Support FastCGI, SSL, Virtual Host, URL Rewrite, Gzip and other functions. and supports many third-party module extensions.
Nginx Download Official website has ready-made, directly download the version of their own computer-like fool-type installation on the line. (Install or unzip do not appear in Chinese)
Locate the conf/nginx.conf file in the inside to modify the settings
- Listen 802: The Port we listen to
- server_name 192.168.1.130: The address of the listener
- Proxy_pass Http://mynginxserver: Jump to the last connection as appropriate
- Configure multiple Tomcat in Mynginxserver:
upstream mynginxserver { server192.168.1.78:8080 weight=1; server192.168.1.130:8080 weight=1; }
- Complete the configuration
Upstream Mynginxserver {Server 192.168. 1. the:8080weight=1;Server 192.168. 1.:8080weight=1; }Server{Listen802; server_name192.168. 1.;#charset koi8-r; #access_log Logs/host.access.log main;Location/{Proxy_pass http://mynginxserver;}#error_page 404/404.html; # REDIRECT Server error pages to the static page/50x.html #Error_page - 502 503 504/ -x.html; Location =/ -x.html {root HTML; }# Proxy The PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # Proxy_pass http://127.0.0.1; #} # Pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root HTML; # Fastcgi_pass 127.0.0.1:9000; # Fastcgi_index index.php; # Fastcgi_param Script_filename/scripts$fastcgi_script_name; # include fastcgi_params; #} # Deny access to. htaccess files, if Apache ' s document Root # concurs with Nginx ' s one # #location ~/\.ht { # deny all; #}}
- This time when we were two tomcat in the running state we entered in the browser
192.168.1.130:802
- The nginx will randomly select a tomcat to run. At the same time, the two Tomcat session is shared. It means that a tomcat session B can be used. Even if a goes down, B also presses the session of a.
With spring session for session sharing
- The above one way I also in the online case operation. Not fit in your project. Because my project is configured with a Redis cluster (non-Sentinel). So the configuration in Tomcat is not possible.
Explanation: The first way to configure Redis by default is single-node Redis. That is, our session will produce SessionID as the key in Redis exists on the library where we configure the Redis node. However, if we are a Redis cluster, the cluster will calculate the slot value based on the key value and decide which Redis service provider to access based on the slot value. That means we have no idea which redis will exist before we save the session. So this approach is not suitable for redis clusters.
Take a look at the mind map I drew:
The second chapter is obviously wrong and is not actually stored on the Redis that implements the contract.
Spring Session Configuration
- Having said that, let's start with the integrated session sharing configuration in spring. First, if you're a MAVEN project, introduce the jar directly.
<dependency> <groupId>org.springframework.session</groupId><artifactId>spring-session</artifactId><version>1.1.1.RELEASE</version></dependency>
- If you are not a MAVEN project, then trouble yourself to download these related jar packages.
spring-data-redis.jarredis.clients.jarspring-session.jar
- Also here you need a few articles to configure the Redis cluster
Point me to see how to configure Redis
Point I see how to configure Redis and spring consolidation
Point I see how to configure a rollup of issues that you encounter in Redis
Spring configuration file Configuration
With the preparation information above, we can configure the spring session in the spring configuration file.
Very simple we need to introduce the Bean in spring session
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"
- In spring's configuration file we just need to configure this one bean. The following is only one step away from sharing the session to a Redis cluster. is to configure the interceptor in the Web. xml file
<filter > << Span class= "hljs-built_in" >filter -name>springsessionrepositoryfilter</-name> <filter -class >org.springframework.web. filter . Delegatingfilterproxy</filter -class ></filter ><filter -mapping > <filter -name>springsessionrepositoryfilter</filter -name> <url-pattern>/*</url-pattern></ filter -mapping>
- When the configuration is complete, we can restart our project and run the section to access the session. Then go to the Redis cluster and find out if there is a session. The key to the default session in Redis is
spring:session:sessions:c0d1fadd-b04a-4244-9525-0f13ea7173bf
. The next string of IDs is the SessionID of our Tomcat and browser sessions.
Problem
In the above we have configured the spring session to implement the session sharing. But a careful friend can find out. The session does not have a real sense of sharing. Above we can see that the key of the session in the Redis cluster contains the SessionID of Tomcat and the browser. That is to say, this session on Redis can only be accessed by my Tomcat on this browser. Other Tomcat can't get the session on Redis even if they interact with the same browser. Is that the effect you want? The answer is not. The effect I've achieved above is described in a picture.
In other words, my configuration above only transfers the Tomcat session to Redis. The multi-service session is still in each district. This is a big hole. Pit for a long time. And then I thought, another way to solve this limitation now.
Solutions
- Solve the above problem. Here I offer three kinds of ideas. Three kinds of ideas I have realized a bit. Each has its pros and cons. Finally decided to adopt a third kind of comparative reliable.
To rewrite the spring session source, rewrite the session stored in the Redis part of the code, mainly to the Redis session key written fixed value. After we go to the session to take this fixed key can be achieved session sharing.
The only way to rewrite our session repository in the spring session is to pass the resulting sessionid to project B after the A project is logged in. Project B is obtained from Redis under this sessionid.
The above two methods need to customize many classes, sorting out the configuration of the custom classes and configuration files. Click I download
3– in place of value in the session, SessionID is used as value, and the host and agent combination in the request header is the most key stored on Redis. Then we go to the spring session in the method of the session in accordance with the host and agent key to get SessionID, and then we can get the corresponding session.
Access Policy refactoring
- Here is the third way to explain the implementation steps. First I create a new class to read the key value of the host and agent stitching in the request's header.
PublicStaticMap<String, Object>Getinfofromurl (HttpServletRequest request) {Map<String, Object>Resultmap=NewHashMap<String, Object>();StringAgent=Request.GetHeader ("User-agent");StringHost=Request.GetHeader ("Host"); Resultmap.Put"Agent", Agent); Resultmap.Put"Host", Host);returnResultmap; } PublicStaticStringGetkeyfromurl (HttpServletRequest request) {StringResult="";Map<String, Object> Map =Getinfofromurl (Request);Set<String>KeySet= Map.KeySet (); for (StringKey:keyset) {Result+=Map.Get (Key).ToString (); }returnResult }
- And then where we call the session where the value is stored, that is where we log in. Store it through the Redis operations class in our project.
- Then we modify the SessionID policy in the cookie repository in the spring session to request the
- At the end of the spring configuration we are modifying the spring session strategy for me your cook strategy
<beanID="Rediscachetemplate" class="Com.bshinfo.web.base.cache.RedisCacheTemplate"/> <beanID="Zxh" class="Com.bshinfo.web.base.cache.CookieHttpSessionStrategyTest"> < Property name="Rediscachetemplate" ref="Rediscachetemplate"/> </bean> <beanclass="Org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"> < Property name="Httpsessionstrategy" ref="Zxh"/> < Property name="Maxinactiveintervalinseconds"Value=" the"/> </bean>
- Finally, we have achieved our results. The effect is that a project is logged on in X browser. b The user who gets the session in X browser can get it normally. Otherwise, the acquisition fails.
Big talk Spring Session sharing