去中心化Session判断与代码实践(SpringSession)

原创
小哥 3年前 (2022-11-08) 阅读数 39 #大杂烩

一、介绍

1、什么是session? cookie?

session对象存储在服务器侧存储器中,cookie存储在客户端浏览器中。通常,客户端请求服务器,服务器生成session对象,将session该对象存储在此后端服务的内存中,并放置在响应头中。sessionId响应客户端,命令客户端保存。sessionid到cookie。当浏览器稍后发送请求时,它将自动发送本地cookie中存储的seesionId通过请求头将其传递给服务器,以便服务器和客户端可以维护会话信息。

2,分发的内容session,为什么分布session?

  1. 为了提高服务器端的负载能力,后台通常通过ngnix通过轮询转发到目标服务器。例如,当浏览器第一次访问时A服务器登录并生成session对象然后第二个请求是访问后台界面,如果它碰巧是ngnix转发到了A服务器,则无法获得任何问题session对象如果请求被转发B服务器,由于以前生成session对象保存在A在服务器中,B服务器根本没有这个。session对象,它将被标识为未登录等。
  2. session不是跨域,它有自己的作用范围,当我们有跨域需求时,我们还需要使用分布式session。例如,在制作购物网站时,单击登录跳转auth.mail.com域名认证微服务登录,但访问。mail.com域名下的其他服务不可用时session,确定不登录。

因此,所谓的分布式session就是要session能够在不同服务和同一服务的集群之间共享。

2.解决方案

1、session复制(不推荐)

用户登录后,他会得到它。session在那之后,发球局放了。session同样复制到其他机器上,显然这种处理非常糟糕,这里只简单介绍一下这种方案。

2、hash一致性(不推荐)

基于用户计算hash值,路由到指定的计算机登录。每个用户每次都会被路由到同一个后台节点,但远程调用仍然不容易解决。

3、springsession整合redis统一存储(推荐)

最终解决方案,集成springsession,把session放到redis在中,后续代码基于此实现。

3.代码执行

1,首先附上正式文件:
https://spring.io/projects/spring-session-data-redis
https://docs.spring.io/spring-session/docs/2.4.2/reference/html5/#modules
核心思想是SpringSession修改session范围

2,依赖项导入和环境配置


    org.springframework.session
    spring-session-data-redis


    org.springframework.boot
    spring-boot-starter-data-redis

在properties添加配置信息。

spring.session.store-type=redis
server.servlet.session.timeout=30m
spring.redis.host=192.168.56.10

在启动类头上添加注释以供打开springsession。

@EnableRedisHttpSession //已创建springSessionRepositoryFilter ,负责将本地HttpSession 替换为Spring Session的实现

3、扩大session范围和设置session序列化

由于默认使用jdk通过导入进行序列化RedisSerializer修改为json序列化。通过修改CookieSerializer扩大session范围**.mall.com。

按如下方式编写配置类:

@Configuration
public class MallSessionConfig {

    @Bean // redis的json序列化
    public RedisSerializer springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

    @Bean // cookie
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("MAILSESSIONID"); // cookie的键
        serializer.setDomainName("mall.com"); // 扩大session范围,即cookie的有效域
        return serializer;
    }
}

请注意,此配置需要放置在 每个 需要共享session在微服务下(无论是读还是写),它不仅仅是写。session在微服务下。

迄今为止,已分发session留着吧。

4,添加:已分发session举个例子

假设您进行登录验证Controller:

@GetMapping({"/login.html","/","/index","/index.html"}) // auth服务
public String loginPage(HttpSession session){
    // 从会话获取loginUser
    Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);// "loginUser";
    System.out.println("attribute:"+attribute);
    if(attribute == null){
        return "login";
    }
    System.out.println("我已登录并重定向到主页。");
    return "redirect:http://mall.com";
}

@PostMapping("/login") // auth服务
public String login(UserLoginVo userLoginVo,
                    RedirectAttributes redirectAttributes,
                    HttpSession session){
    // 调用远程登录界面以验证帐户密码是否正确
    R r = memberFeignService.login(userLoginVo);
    if(r.getCode() == 0){
        // 登录成功
        MemberRespVo respVo = r.getData("data", new TypeReference() {});
        // 放入session  // key为loginUser
        session.setAttribute(AuthServerConstant.LOGIN_USER, respVo);//loginUser
        log.info("

欢迎 [" + respVo.getUsername() + "] 登录"); // 登录成功重定向到主页 return "redirect:http://mall.com"; }else { HashMap<String, String> error = new HashMap<>(); // 获取错误信息 error.put("msg", r.getData("msg",new TypeReference(){})); redirectAttributes.addFlashAttribute("errors", error); return "redirect:http://auth.mall.com/login.html"; } }

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门