一:session问题

session底层就是服务器的一片内存空间,相当于map

spring boot 设置 shiro 会话时长_服务器

  • 1.不能跨域名进行共享
  • 2.同一个服务,复制多份,session不同步问题

二:session共享问题解决

1.session复制(不采用)

优点:

  • web-server(Tomcat)原生支持,只需要修改配置文件

缺点:

  • session同步需要数据传输,占用大量网络带宽,降低了服务器群的业务处理能力。
  • 任意一台web-server保存的数据都是所有web- server的session总和,受到内存限制无法水平扩展 更多的web-server
  • 大型分布式集群情况下,由于所有web-server都全 量保存数据,所以此方案不可取。

2.客户端存储(不采用)

优点:

  • 服务器不需存储session,用户保存自己的 session信息到cookie中。节省服务端资源

缺点:都是缺点,这只是一种思路。

  • 每次http请求,携带用户在cookie中的完整信息, 浪费网络带宽 ,不安全
  • session数据放在cookie中,cookie有长度限制 4K,不能保存大量信息
  • session数据放在cookie中,存在泄漏、篡改、 窃取等安全隐患

3.hash一致性

spring boot 设置 shiro 会话时长_redis_02


spring boot 设置 shiro 会话时长_服务器_03


优点:

• 只需要改nginx配置,不需要修改应用代码

• 负载均衡,只要hash属性的值分布是均匀的,多台 web-server的负载是均衡的

• 可以支持web-server水平扩展(session同步法是不行 的,受内存限制)

缺点:

• session还是存在web-server中的,所以web-server重 启可能导致部分session丢失,影响业务,如部分用户 需要重新登录

• 如果web-server水平扩展,rehash后session重新分布, 也会有一部分用户路由不到正确的session

• 但是以上缺点问题也不是很大,因为session本来都是有有 效期的。所以这两种反向代理的方式可以使用

4.统一存储(推荐)

spring boot 设置 shiro 会话时长_服务器_04


优点:

• 没有安全隐患

• 可以水平扩展,数据库/缓存水平切分即 可

• web-server重启或者扩容都不会有 session丢失

缺点:
• 增加了一次网络调用,并且需要修改应 用代码;如将所有的getSession方法替 换为从Redis查数据的方式。redis获取数 据比内存慢很多
• 上面缺点可以用SpringSession完美解决

三:SpringBoot整合SpringSession——完成session共享

1.引入依赖

<!--引入springSession-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

2.配置文件配置session类型

#redis的连接信息
spring.redis.host127.0.0.1
spring.redis.port=6389
#session的类型
spring.session.store-type=redis
#session的过期时间
server.servlet.session.timeout=30m

3.在主启动类添加@EnableRedisHttpSession

//整合redis作为session存储
@EnableRedisHttpSession

四:子域session共享问题

1.新建GulimailSessionConfig配置类

@Configuration
public class GulimailSessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        //指定作用域
        cookieSerializer.setDomainName("");
        //设定cookie名字
        cookieSerializer.setCookieName("GULISESSION");
        return cookieSerializer;
    }
    /**
     * 设置序列化机制
     * @return
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer(){
        return new GenericJackson2JsonRedisSerializer();
    }

}

五:SpringSession核心原理

1.@EnableRedisHttpSession注解原理

1)EnableRedisHttpSession导入了RedisHttpSessionConfiguration

给容器中添加了组件

  • RedisOperationsSessionRepository,redis操作session的增删改查
  • SessionRepositoryFilter:session存储的过滤器,每个请求就需要经过过滤器。创建的时候就自动创建了。

2.核心代码

spring boot 设置 shiro 会话时长_spring_05

  • 放行包装之后的request和response应用到执行链。
  • 以后获取session:wrappedRequest.getSession()中获取
  • session会自动延期

六:用户名密码登录整合session

1.代码实现

@PostMapping("/login")
    public String login(UserLoginVO vo, RedirectAttributes redirectAttributes, HttpSession session){
        //远程登录
        R r = memberFeignService.login(vo);
        if(r.getCode() == 0){
            //往session中去保存数据
            MemberRespVo data = r.getData(new TypeReference<MemberRespVo>(){});
            session.setAttribute(AuthServerConstant.LOGIN_USER,data);
            //成功就去首页
            return "redirect:http://127.0.0.1:10000";
        } else {
            Map<String, String> errors =new HashMap<>();
            errors.put("mag",r.getData(new TypeReference<String>(){}));
            redirectAttributes.addFlashAttribute("errors",errors);
            //失败就去登录页
            return "redirect:http://127.0.0.1:20000/login.html";
        }
    }

2.登录的时候先看session中有没有用户信息,如果有就不需要登录了。