Session Detailed mechanisms and sharing solutions distributed in Session

First, why should generate Session

  http protocol itself is stateless, the client only needs to request the download server, the client and the server does not record another historical information, each request is independent.

  Why is stateless it? Because the browser and the server is using socke socket communication, the server requests the results after the return to the browser, it will close the current socket link, and the server will be destroyed after processing the page object page is completed.

  However, in many scenarios need to maintain user state Web applications to work properly (if login, etc.), or provide convenient (remember passwords, browsing history, etc.), is a very important to maintain functional status. Therefore, web application development where there have been kept http link status of technology: one cookie technology, the other is the technical session.

Two, Session what role, how to produce and play a role

  To understand Session would have to figure out what is Cookie, Cookie and Session and the relationship of.

  1. What is a Cookie

  Cookie technology is http client state remains in solution, Cookie is a special message from the server to the client, and the information to a text file stored on the client, and then when the client sends a request to the server each time will bring the these special information.

  2, Cookie generation

  When visiting a site supports Cookie when first-time users of the browser, the user will provide personal information including user names, including and submitted to the server; then, the server will send back to the client in return, while the corresponding hypertext personal information, of course, such information is not stored in the HTTP response body (response body) is, but is stored in the HTTP response header (response header); when the client browser receives a response from the server, the browser will This information is stored in a single location.

  cookie stored on the hard disk can not be between different browser sharing, can be shared between different processes in the same browser, such as two IE windows. This is because the position of each cookie stored in the browser is not the same, such as

  Chrome下的cookie放在:C:\Users\sharexie\AppData\Local\Google\Chrome\User Data\Default\Cache

  cookie placed under Firefox: C: \ Users \ sharexie \ AppData \ Roaming \ Mozilla \ Firefox \ Profiles \ tq2hit6m.default \ cookies.sqlite (penultimate file name is random file name)

  cookie placed under Ie: C: \ Users \ Administrator \ AppData \ Roaming \ Microsoft \ Windows \ Cookies

  3, Cookie content, scope and validity

  the cookie should include: name, value, expiration time, path and domain. Path field together constitute the scope of the cookie.

  If you do not set an expiration time, then the lifetime of the cookie for the duration of the browser session, simply close the browser window, cookie disappeared, such as the lifetime of the browser session cookie is called a session cookie. Session cookie is generally not stored on the hard but stored in memory. If you set the expiration time, the browser cookie will be saved to your hard drive, open the browser again after closing, these cookie remain valid until the expiration time exceeds the set.

  4, Cookie How to use

  cookie use is automatically sent to the server by the browser in accordance with certain principles in the background.

  When a client sends a request to the secondary server, the browser checks all stored cookie, a cookie if the scope is not less than the stated location of the resources will be requested, put the cookie attached to the request resource HTTP request head sent to the server. Cookie With this technology, the server after receiving a request from a client browser, the analysis can be stored in a Cookie request header resulting client-specific information to dynamically generate content corresponding to the end customer. In general, we can see a lot of sites from the login screen in "Remember Me" this option, and then log on later if you check it, the next time you visit the site does not need to be repeated and tedious login the action, and this feature is implemented by Cookie.

  5. What is Session

  Session commonly called answer, Technical Session state is maintained at http server solution, which is to maintain the state of the server. We can put in motion a series of interactions between the client browser and the server is called a Session. Is the server for the client to open up storage space in which to save the information that is used to hold. Therefore, session is to solve the problem of stateless http protocol server solution that allows the client and server interact with a series of actions into a complete transaction.

  6, Session created

  Then in Session when to create it? Of course, there are different ways to create Session or created during the server program is running, the application of different language.

  When a client requests the server for the first time, the time when the server-side program call such a statement HttpServletRequest.getSession (true), the server creates a session for the client, and the session ID is calculated by a special algorithm for identify the session object.

  Session stored in memory of the server (Tomcat server by the session class StandardManager stored in memory), may also be persisted to the File, database, memcache, redis like. The client only to save sessionid cookie, but not saved session.

  The browser is closed and will not result in the deletion of Session, only when the time-out, the program calls HttpSession.invalidate () and close the server program will be deleted.

  7, Tomcat created in Session

  ManagerBase is the base class for all session management tools, which is an abstract class, all the realization session management classes should inherit this class, which has a protected method, this method is the method sessionId value creation:

(Mechanism of the session id value tomcat generated random number is a value added time plus the jvm id, the id value is based jvm hardware information calculated to a server, and therefore different values ​​are the jvm unique id).
  StandardManager tomcat container class is the default implementation class session management, session information that will be stored in the memory of the server where the web container.
  PersistentManagerBase is inherited ManagerBase class, which is the base class for all the persistent store session information, PersistentManager inherited PersistentManagerBase, but this is just one more class static variable and a getName method, it seems of little significance for persistent storage session, also provided StoreBase tomcat abstract class, it is all persistent storage base class session, further tomcat also given file storage and a data storage JDBCStore two FileStore achieved.

  8, Cookie and Session relationship

  cookie and session program, although belonging to the client and server, but realize session of the server are on the client's cookie dependencies, server-side execution session mechanism when it will generate an id value of the session, the id value is sent to the client the client id every request put this value into the head http request to the server, and the client id value preserved, save that cookie containers, so when we completely ban the browser cookie time, session server will not work properly.

Third, the distributed system Session Sharing

  Session is actually a cluster of servers sharing issues, the client and server communication session to keep the course, the entire recording session Session communicate basic information. However, in a clustered environment, it assumes that the client for the first time to access the service A, the service returns a response A sessionId and stored in the local Cookie. A second not access the service, and turn to access the service B. Because the client Cookie of the sessionId already there, so when accessing the service B, sessionId will be added to the request header, and the service B because there is no corresponding data found by sessionId, so it will create a new sessionId and returns the response to the client. This has caused the problem can not be shared Session.

  For example, in SpringCloud project, start a service, respectively, with two different ports, and then registered in Eureka Server, then thus forming a cluster of two servers, Ribbon load balancing policy is set to polling policy. The processing request to the server:

@RestController
public class TestSessionController {

    @Value("${server.port}")
    private Integer projectPort;// 项目端口

    @RequestMapping("/createSession")
    public String createSession(HttpSession session, String name) {
        session.setAttribute ( "name" , name);
         return "current project Port:" + projectPort + "Current sessionId:" + session.getId () + " into success in Session!" ;
    }

    @ RequestMapping ( "/ getSession" )
     public String getSession (the HttpSession the session) {
         return "current project Port:" + projectPort + "Current sessionId:" + session.getId () + " to obtain the name:" + session.getAttribute ( " name " );
    }

}

  We accessed through a polling mechanism first deposit directly to the Session in a name, http: //www.hello.com/createSession name = AAA?

Current projects Port: 8081 Current sessionId: 0F20F73170AE6780B1EC06D9B06210DB into success in Session!

  Since we are using the default polling mechanism, the next visit is sure port 8080, we have direct access to the following value http://www.hello.com/getSession just deposit

Current projects Port: 8080 Current sessionId: C6663EA93572FB8DAE27736A553EAB89 get the names: null

  8080 port and found no value in our stores, and also different sessionId and 8081 ports.

  Because this time we are polling mechanism server port 8081, then before we are into a name in 8081, the server port 8080 is not stored in the Session.

  Then we revisit 8081 Port Services to see if we can get into the name: AAA, continue to visit: http: //www.hello.com/getSession

Current projects Port: 8081 Current sessionId: 005EE6198C30D7CD32FBD8B073531347 get the names: null

  Found that not only port 8080, not even 8081 before being stored off the port as well.

  In fact, discovery port sessionid third visit in 8081 are not the same, because at the time we visited a second time to visit the port this time is 8080 client gets to go on port 8081 of 8080 server in a cookie, not found after re-create a session and sessionid response to the client, the client while maintaining cookid to replace the sessionid before 8081, when it took the third visit of the sessionid second visit of then find they can not find they created. Has been repeated cycle, two servers will always get the other side is generated sessionId, get sessionId own generation, which is a cluster Session Sharing.

Fourth, how to solve shared problems Session

  Common Session Sharing program are summarized as follows:

  • Use the cookie to complete (obviously unsafe operation is not reliable)
  • Use the ip binding policy Nginx, the same ip can only access the same machine specified (does not support load balancing)
  • Use database synchronization session (inefficient)
  • Tomcat session using the built-in synchronization (sync may cause delays)
  • Instead of using a token session
  • Use Spring-Session + Redis implemented

  1, to achieve Cookie

  This is the principle way to encrypt Session information system users, after serialization, to Cookie way, planting unified under the root domain (such as: .host.com), use a browser to access all second-level domain under the root domain sites when will the transfer characteristic of all the contents of the Cookie domain names corresponding thereto, enabling users of the Session Cookie shared access between multiple services.

  The advantage of this scheme without additional server resources ; disadvantage is the limitation header length http protocol by only capable of storing user information of the small section , while Cookie of the Session content requires a secure encryption (eg: using DES, RSA, etc. plain text encryption and decryption; then a MD5, SHA-1 algorithms security authentication), while it takes a certain amount of bandwidth , because the browser will any resource in the local Cookie attached at the request of the current domain name transmitted in the http header to the server, the most important is a security risk .

  2, using the ip binding policy Nginx

  This simply Nginx configuration in a ip_hash; on it, but the disadvantage of this approach is also evident, configure the IP Binding Nginx does not support the load balancing. Specific reference blog: https://www.cnblogs.com/ywb-articles/p/10686673.html

  3, using a database synchronization session

  That MySQL, for example, each session will save the data into the database. This program is quite feasible, many developers use this approach. But its disadvantage is that concurrent read and write Session capability depends on the performance of the MySQL database, the database of the large pressure, while the need to achieve their elimination Session logic to update from the timing data table, delete the record Session, concurrently too easily when table lock occurs, although you can choose a table row-level locking engine, but many people in this program is not the optimal solution.

  4, instead of using the session token

  Here token is JSON Web Token, generally use it to replace in Session data sharing.

  Use the Token-based authentication methods, logon recorded in the server does not need to store the user. Probably the process is this: 

      1, the client user name and password to log server;
      2, the server to the client identity verification;
      3, the server the user-generated Token, returned to the client;
      4, the client Token saved to the local browser, general saved in a cookie;
      5, the client sends a request, we need to carry the Token;
      6, after the server receives a request, first verify that the Token, then returned data.

        

  As shown above, the left is a Token implementations, there is photo session implementations, the flow is substantially uniform. Specific Reference: https://www.cnblogs.com/lightzone/p/9749076.html

  The first browser to access the server, based on the unique identifier userId, the server will pass over through some algorithms, such as the commonly used HMAC-SHA256 algorithm, and then add a key to generate a token, and then look through the BASE64 encoded after this token to the client; client token saved, the next request with the token, the server receives the request, and will use the same algorithm and key token to verify, if adopted, performs traffic operations, not through, returns through information.

  advantage:

  • Stateless, scalable: In the Token stored by the client is stateless, and can be extended. Based on this storage state and a non-Session information, the load balancer can be transmitted to the user information from a service on another server.
  • Security: sending the request token cookie instead of transmitting CSRF can be prevented (cross-site request forgery).
  • May provide an interface to third-party services: When using the token, offers optional permissions to third-party applications.
  • Multi-platform cross-domain

  对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。 假如我们的后端api服务器a.com只提供数据,而静态资源则存放在cdn 服务器b.com上。当我们从a.com请求b.com下面的资源时,由于触发浏览器的同源策略限制而被阻止。

  我们通过CORS(跨域资源共享)标准和token来解决资源共享和安全问题。

  举个例子,我们可以设置b.com的响应首部字段为:

Access-Control-Allow-Origin: http://a.com

Access-Control-Allow-Headers: Authorization, X-Requested-With, Content-Type, Accept

Access-Control-Allow-Methods: GET, POST, PUT,DELETE

  第一行指定了允许访问该资源的外域 URI。

  第二行指明了实际请求中允许携带的首部字段,这里加入了Authorization,用来存放token。

  第三行用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。

  然后用户从a.com携带有一个通过了验证的token访问B域名,数据和资源就能够在任何域上被请求到。

  5、使用tomcat内置的session同步

  5.1 tomcat中server.xml直接配置

<!-- 第1步:修改server.xml,在Host节点下添加如下Cluster节点 -->
<!-- 用于Session复制 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
    <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true" />
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" 
                    port="45564" frequency="500" dropTime="3000" />
        <!-- 这里如果启动出现异常,则可以尝试把address中的"auto"改为"localhost" -->
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" 
                  autoBind="100" selectorTimeout="5000" maxThreads="6" />
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor" />
    </Channel>
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter="" />
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />
    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" 
              deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false" />
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>

  5.2 修改web.xml

  web.xml中需加入<distributable/> 以支持集群。

<distributable/>

  5、Spring-Session+Redis实现

  Spring提供了一个解决方案:Spring-Session用来解决两个服务之间Session共享的问题。

  5.1 在pom.xml中添加相关依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

  5.2 修改application.properties全局配置文件(本地要开启redis服务)

spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=8
spring.redis.timeout=10000

  5.3 在代码中添加Session配置类

/**
 * 这个类用配置redis服务器的连接
 * maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
 */
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
    // 冒号后的值为没有配置文件时,制动装载的默认值
    @Value("${redis.hostname:localhost}")
    private String hostName;
    @Value("${redis.port:6379}")
    private int port;
    // @Value("${redis.password}")
    // private String password;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(hostName);
        redisStandaloneConfiguration.setPort(port);
        // redisStandaloneConfiguration.setDatabase(0);
        // redisStandaloneConfiguration.setPassword(RedisPassword.of("123456"));
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public StringRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }
}

  5.4 初始化Session配置

/**
 * 初始化Session配置
 */
public class RedisSessionInitializer extends AbstractHttpSessionApplicationInitializer {
    public RedisSessionInitializer() {
        super(RedisSessionConfig.class);
    }
}

  Spring-Sesion实现的原理

  当Web服务器接收到请求后,请求会进入对应的Filter进行过滤,将原本需要由Web服务器创建会话的过程转交给Spring-Session进行创建Spring-Session会将原本应该保存在Web服务器内存的Session存放到Redis中。然后Web服务器之间通过连接Redis来共享数据,达到Sesson共享的目的。

Guess you like

Origin www.cnblogs.com/jing99/p/11785070.html