• 分布式环境下Session共享问题解决和原理讲解


    1、分布式环境下Session共享问题:

    2、几种解决方法

    3、通过后端统一存储方法在实际项目中问题的体现:

    当session的作用域只限于auth.gulimall.com时,在auth.gulimall.com下登录账号所返回包含用户信息的session无法共享给gulimall.com

    当我们把作用域放大更改为.gulimall.com时,auth.gulimall.com下登录账号所返回包含用户信息的session就能共享给gulimall.com

     

     至此解决session共享跨域问题的核心关键为放大session的作用域范围。

    4、利用SpringSession作用域问题

    ①导入必要的包

            <!--springsession解决session共享问题-->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <version>2.2.0.RELEASE</version>
            </dependency>

    ②在需要进行session共享的微服务的配置文件中添加指定session存取至redis

    spring.session.store-type=redis

    ③在需要进行session共享的微服务主启动类上开启reids的session的存取功能

    @EnableRedisHttpSession//整合redis作为session存取
    @EnableDiscoveryClient
    @EnableFeignClients
    @SpringBootApplication
    public class GulimallAuthServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GulimallAuthServerApplication.class, args);
        }
    
    }
    
    
    
    
    @EnableRedisHttpSession//整合redis作为session存取
    @EnableCaching
    @EnableFeignClients(basePackages = "com.atguigu.gulimall.product.feign")
    @EnableDiscoveryClient
    @MapperScan(basePackages = "com.atguigu.gulimall.product.dao")
    @SpringBootApplication
    public class GulimallProductApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GulimallProductApplication.class, args);
        }
    
    }

    ④让session在不同域名下进行共享并对session进行序列化并以json格式的方式储存

    官方文档:

     实际代码:

    @Configuration
    public class GulimallSessionConfig {
        //解决session跨域问题
        @Bean
        public CookieSerializer cookieSerializer() {
            DefaultCookieSerializer cookieSerializer= new DefaultCookieSerializer();
            //将session作用域放大到*.gulimall.com
            cookieSerializer.setDomainName("gulimall.com");
            cookieSerializer.setCookieName("GULISESSION");
    /*        serializer.setCookieName("JSESSIONID");
            serializer.setCookiePath("/");
            serializer.setDomainNamePattern("^.+?\.(\w+\.[a-z]+)$");*/
            return cookieSerializer;
        }
    
        //Session序列化后转为json格式
        @Bean
        public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
            return new GenericJackson2JsonRedisSerializer();
        }
    }

    5、结果:

    当我在auth.gulimall.com域名下的登录服务下将用户的账户信息传入session时:

    if (oauthlogin.getCode()==0){
         MemberResVo data = oauthlogin.getData("data", new TypeReference<MemberResVo>() {});
         //TODO:1、session只作用当前域,无法跨域访问
         //TODO:2、希望能使用JSON序列化对象
    
         session.setAttribute("loginUser",data);
         return "redirect:http://gulimall.com";
    }

    此处使用MemberResVo实体类,所以要对其进行序列化:

    @ToString
    @Data
    public class MemberResVo implements Serializable {
        private Long id;
        /**
         * 会员等级id
         */
        private Long levelId;
        /**
         * 用户名
         */
        private String username;
        /**
         * 密码
         */
        private String password;
        
       //private .....
       //private .....
    }

    至此我们可以将session返回给gulimall.com取得值并进行显示:

    <a href="http://auth.gulimall.com/login.html">你好,[[${session.loginUser!=null?(session.loginUser.nickname!=null?session.loginUser.nickname:session.loginUser.socialUid):'请登录'}]]</a>

    6、@EnableRedisHttpSession原理

    @EnableRedisHttpSession导入RedisHttpSessionConfiguration.class
    1、RedisHttpSessionConfiguration在容器中添加了RedisIndexedSessionRepository组件:redis操作session,对数据进行持久化处理

    2、被RedisHttpSessionConfiguration继承的SpringHttpSessionConfiguration中添加了SessionRepositoryFilter(session过滤器)
    2.1、SessionRepositoryFilter创建时自动获取到SessionRepository;
    2.2、SessionRepositoryFilter的doFilterInternal方法把原生的request和response被包装成wrappedRequest和wrappedResponse,以后获取session将不再通过原生的request.session()方法而是通过wrappedRequest.getsession(),wrappedRequest.getsession()方法中重写了request.session(),wrappedRequest.getsession()的session是从SessionRepository获取得到的,做到从redis获取session

    核心代码:

    所以,我们可以通过自定义SessionRepository接口更改对session的增删查改方法

  • 相关阅读:
    xshell入门及Linux常用命令
    C++之vector
    c++ 之 string
    引用 与 指针
    关于时间复杂度的计算以及相关概念
    位运算
    thymeleafDemo
    面试总结
    关于mvvm原理实现,模拟vue(3)-----发布订阅
    关于mvvm原理实现,模拟vue(2)-----模板编译
  • 原文地址:https://www.cnblogs.com/linchenguang/p/13517076.html
Copyright © 2020-2023  润新知