• 使用SpringSession管理分布式系统的会话Session


    在我方供应链项目分布式部署的环境下,需要在统一网关服务中管理访问的Session,即无论访问请求路由到哪一个网关服务环境,使用的都是相同的HttpSession,这样就保证了在用户登录之后,能够使用统一的Session来处理鉴权和其他逻辑,这对于分布式系统的用户会话管理是必要的。为了能够达到这个目的,我们引入了SpringSession。

    SpringSession是什么

    SpringSession是Spring框架大集合下的一个子组件,使用Redis来备份Web服务访问生成的(被加工过的)HttpSession,当你在使用SpringBoot框架的时候,你能够很方便的集成和使用它。

    SpringSession如何使用

    1、增加依赖

    当你在使用SpringBoot框架并采用maven来管理依赖库时,你只需增加下面的依赖:

    1 <dependencies>
    2     <!-- ... -->
    3 
    4     <dependency>
    5         <groupId>org.springframework.session</groupId>
    6         <artifactId>spring-session-data-redis</artifactId>
    7     </dependency>
    8 </dependencies>

    幸运的是,当你在使用SpringBoot框架时,你不需要手动指定依赖的具体版本,它会帮你自动管理。

    2、SpringBoot配置项

    得益于SpringBoot的自动配置管理支持,在设置使用Redis备份SpringSession时,我们只需要在application.properties增加如下内容:

    # Session store type.
    spring.session.store-type=redis 

    在如上的配置驱动下,我们再在SpringBoot的配置管理下增加@EnableRedisHttpSession注解,它会自动创建一个名称为SpringSessionReposityFilter且实现了Filter接口的(过滤器)类,这个过滤器将负责替换HttpSession的实现为SpringSession。

    更多关于SpringSession的配置如下:

    # Session timeout. If a duration suffix is not specified, seconds is used.
    server.servlet.session.timeout= 
    
    # Sessions flush mode.
    spring.session.redis.flush-mode=on-save 
    
    # Namespace for keys used to store sessions.
    spring.session.redis.namespace=spring:session 

    3、配置Redis连接

    其实SpringBoot会自动创建一个叫做RedisConnectionFactory的类来管理SpringSession与Redis服务的连接,默认是连接到localhost端口为6379的Redis服务,但是在生产环境中,那就必须将这种与Redis服务器连接的配置进行自定义更改,你可以按照如下代码清单所例举的方式将配置追加到application.properties文件中:

    # Redis server host.
    spring.redis.host=localhost 
    
    # Login password of the redis server.
    spring.redis.password= 
    
    # Redis server port.
    spring.redis.port=6379 

    当然,如果你的SpringBoot中自有管理与Redis服务器的连接,你同样可以在你的Configuration将这个连接复用给这里的配置,比如你使用JedisShardInfo。

    以下是使用JedisShardInfo的代码参考:

     1 @Bean("jedisShardInfo")
     2 public JedisShardInfo jedisShardInfo(@Value("${jedis.redis.uri}") String uri,
     3                                      @Value("${catalog.redis.tesla}") String redisCatalog) {
     4     String redisUri = uri;
     5     redisUri = getRedisUri(redisCatalog, redisUri);
     6     return new JedisShardInfo(redisUri);
     7 }
     8 
     9 private String getRedisUri(String redisCatalog, String redisUri) {
    10     if(!StringUtils.isEmpty(redisCatalog)) {
    11         log.info("===> Redis use unified configuration.");
    12         DataSourceInstanceConfig dbInstanceConfig = DBLoader.getDataSourceInstanceConfig(redisCatalog);
    13         RedisServerInfo serverInfo = dbInstanceConfig.getServer(RedisServerInfo.class).get(0);
    14         redisUri = REDIS_URI_PREFIX.concat(serverInfo.getPassword()).concat("@")
    15                 .concat(serverInfo.getHost()).concat(":")
    16                 .concat(serverInfo.getPort()).concat("/")
    17                 .concat(serverInfo.getDb());
    18         log.info("===> redis_uri: {}", redisUri);
    19     }
    20     return redisUri;
    21 }
    22 
    23 @Configuration
    24 @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 172800)
    25 public class HttpSessionConfig {
    26     @Bean
    27     public static ConfigureRedisAction configureRedisAction() {
    28         return ConfigureRedisAction.NO_OP;
    29     }
    30 
    31     @Bean
    32     public JedisConnectionFactory connectionFactory(@Autowired @Qualifier("jedisShardInfo") JedisShardInfo jedisShardInfo){
    33         return new JedisConnectionFactory(jedisShardInfo);
    34     }
    35 }
    View Code

    4、Servlet容器初始化

    在SpringBootConfiguration的配置驱动下,自动创建的SpringSessionRepositoryFilter将负责替换系统的HttpSession为SpringSession并保存于redis中,为了这个拦截器能够发挥作用,Spring需要将这个过滤器纳入配置管理,最后我们还需要确保Servlet容器能够正确的使用这个拦截器拦截到所有请求,幸运的是,SpringBoot为我们顾及到了所有的这些步骤。

    SpringSession的实现原理是什么

    和我们使用Tomcat的HttpSession不同的是,我们将这个会话内容持久化到了Redis中。SpringSession将HttpSession替换为一种新的实现,并将它保存到了Redis中,也就是当我们的SpringSecurity的SecurityContextPersistenceFilter在保存了SecurityContext到HttpSession之后,就会触发这个替换机制保存到Redis中。

    当我们发起访问请求的时候,系统会创建一个HttpSession,而SpringSesion会创建一个名称为SESSION的cookie放到你浏览器的中,这个cookie的内容包含了你session的ID,你可以在你的Chrome浏览器控制台中查看到。

    于此同时,你也可以在你的redis服务器中看到,找到以application.properties中配置的命名空间开头的key值,然后你会看到包含和浏览器上看到的SESSION相同内容的key,当然你可以在redis服务器中使用redis-cli命令去查看或者删除它。

    当你浏览器每次发起Http请求到服务端时,都会携带这个cookie内容,服务端SpringSession接受到这个cookie值之后就自动去redis中找到相同的会话Session,由此来识别出是同一个用户进行的访问。

    参考资料

    1、https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html

    2、http://blog.didispace.com/spring-session-xjf-2/

  • 相关阅读:
    webshell
    FireFox与IE开发上的一些区别
    面向对象的Jscript(顶)
    CSS背景属性
    [转]javascript中style.left和offsetLeft的使用
    BLOG排版小窍门
    面向对象的JavaScript编程
    Js脚本:动态添加HTML自定义属性以及处理html元素的自定义属性(兼容Firefox和IE)
    lookupedit 设置选项值
    comboboxEdit 不能输入,只能选择
  • 原文地址:https://www.cnblogs.com/captainad/p/10861006.html
Copyright © 2020-2023  润新知