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

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

分布式环境下Session共享问题解决和原理讲解_第1张图片

2、几种解决方法

分布式环境下Session共享问题解决和原理讲解_第2张图片

分布式环境下Session共享问题解决和原理讲解_第3张图片

分布式环境下Session共享问题解决和原理讲解_第4张图片

分布式环境下Session共享问题解决和原理讲解_第5张图片

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

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

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

 

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

4、利用SpringSession作用域问题

①导入必要的包

        
        <dependency>
            <groupId>org.springframework.sessiongroupId>
            <artifactId>spring-session-data-redisartifactId>
            <version>2.2.0.RELEASEversion>
        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格式的方式储存

官方文档:

分布式环境下Session共享问题解决和原理讲解_第6张图片

 实际代码:

@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 springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

5、结果:

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

if (oauthlogin.getCode()==0){
     MemberResVo data = oauthlogin.getData("data", new TypeReference() {});
     //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取得值并进行显示:

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

核心代码:

分布式环境下Session共享问题解决和原理讲解_第7张图片

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

 

你可能感兴趣的:(分布式环境下Session共享问题解决和原理讲解)