集群session的共享问题

news2024/11/24 12:28:31

基于redis实现共享session登录

1.集群session共享的问题

session共享问题:多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时导致数据丢失问题

替代方案应该满足:

数据共享

内存存储

key、value结构

 

2.基于redis实现session共享登录

 

需要生成token令牌,通过token的值去确定哪个用户做出请求

将token作为key用户信息作为值存储到redis中,利用的模板时StringRedisTemplate这样不仅可以节省服务器的空间还增加可读性

@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {
    //1.校验手机号的格式
    String phone = loginForm.getPhone();
    if (RegexUtils.isPhoneInvalid(phone)) {
        //2.不一致直接报错
        return Result.fail("手机号错误");
    }
    //3.比较验证码
    String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);
    String code = loginForm.getCode();
    if(session==null || !cacheCode.equals(code)){
        //4.不一致直接报错
        return Result.fail("错误信息");
    }
    //5.根据手机号查询用户
    LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
    query.eq(User::getPhone,loginForm.getPhone());
    User user = this.getOne(query);
    if(user==null){
        //6.不存在直接创建新用户保存到数据库中
        user=createUserWithPhone(loginForm.getPhone());
    }
    UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
    //7.最终将用户信息保存到redis中  使用UserDTO保护用户的隐私
    //7.1生成token
    String tokenKey = UUID.randomUUID().toString();
    /*
    * 当用户第一次登录后,服务器生成一个token并将此token返回给客户端,
    * 以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。
    * */
    //7.2 将user转为hash存储
    Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(), CopyOptions.create()
    .setIgnoreNullValue(true)
    .setFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));
    //7.3存储
    stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY+tokenKey,userMap);
    //7.4设置存储的生命周期
    /*
    * 这里设置过30min会自动从redis中剔除 但我们想要的效果是30min没有用到token时剔除
    * 这时我们需要去拦截器里面设置并且刷新token
    * */
    stringRedisTemplate.expire(LOGIN_USER_KEY+tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);
    //8.返回给客户端
    return Result.ok(tokenKey);
}

拦截器的设定之前设置的拦截器放行了部分页面,如果我们只访问那种部分页面时拦截器直接放行导致不能够刷新redis中的数据,现在设定两个拦截器,一个负责专门刷新redis的生命周期,另一个负责拦截

//注册拦截器  及其相关配置
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    //添加拦截器
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //order的值越小 执行的优先级越高
        //登录拦截器
        registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(
                "/shop/**",
                "/voucher/**",
                "/shop-type/**",
                "/upload/**",
                "/blog/hot",
                "/user/code",
                "/user/login"
        ).order(1);
        //刷新拦截器  拦截所有
        registry.addInterceptor(new ReFreshTokenInterceptor(redisTemplate)).order(0).addPathPatterns("/**");
​
    }
}
​
@SuppressWarnings("all")
//创建拦截器
public class ReFreshTokenInterceptor implements HandlerInterceptor {
    //有注册拦截器注入bean
    private StringRedisTemplate stringRedisTemplate;
​
    public ReFreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取token
        String token = request.getHeader("authorization");
        if(StringUtils.isEmpty(token)){
            return true;
        }
        //2.通过token从redis中拿到用户信息
        Map<Object, Object> user = stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY+token);
        if(user.isEmpty()){
​
            return true;
        }
        //4.存在  将Map对象转为UserDto对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(user, new UserDTO(), false);
        //5.存储到ThreadLocal中
        UserHolder.saveUser(userDTO);
        //6.设置token的刷新时间
        stringRedisTemplate.expire(LOGIN_CODE_KEY+token,LOGIN_USER_TTL, TimeUnit.MINUTES);
        //5.放行
        return true;
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //避免造成内存泄露
        UserHolder.removeUser();
    }
}
public class LoginInterceptor implements HandlerInterceptor {
    //有注册拦截器注入bean
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //1.只需要判断ThreadLocal中有没有用户信息
        if(UserHolder.getUser()==null){
            //响应未授权的状态信息
            response.setStatus(401);
            //拦截
            return false;
        }
        //放行
        return true;
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //避免造成内存泄露
        UserHolder.removeUser();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/499760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QoS实验配置-基于类部署

目录 对路由进行优先级标记 配置端口信任DSCP优先级 配置流量监管 配置拥塞管理 配置拥塞避免 配置流量整形 出接口下应用队列模板 对配置进行检验 QoS基于类的方式实现管理&#xff08;通过调度0~7队列进行实现&#xff0c;一般6、7协议是预留给路由协议的&#xff0c…

macos和windows区别 macos怎么运行windows程序

在我们使用电脑时&#xff0c;重要的是电脑内应用&#xff0c;而系统不过是运行软件的“容器”。日常生活中&#xff0c;我们常见的操作系统是macos和windows&#xff0c;那么macos和windows区别在哪&#xff1f;这两款操作系统的区别很大。macos怎么运行windows程序&#xff1…

从I帧到B帧,H.264编码技术为您构建画面与效果完美结合的视觉盛宴

H264之帧编码 H.264&#xff0c;也称为 MPEG-4 AVC (Advanced Video Coding)&#xff0c;是一种高效的视频编码标准&#xff0c;用于压缩和存储视频。H.264 利用了预测编码和变换编码等先进的技术&#xff0c;其编码流程与普通视频编码类似&#xff0c;主要包括帧类型判定、运…

2017年下半年软件设计师下午试题

试题四 阅读下列说明和C代码&#xff0c;回答问题1至问题 2&#xff0c;将解答写在答题纸的对应栏内。 【说明】 一个无向连通图G点上的哈密尔顿&#xff08;Hamiltion&#xff09;回路是指从图G上的某个顶点出发&#xff0c;经过图上所有其他顶点一次且仅一次&#xff0c;最后…

HNU-操作系统OS-实验Lab4

OS_Lab4_Experimental report 湖南大学信息科学与工程学院 计科 210X wolf &#xff08;学号 202108010XXX&#xff09; 实验目的 了解内核线程创建/执行的管理过程了解内核线程的切换和基本调度过程 实验内容 lab2/3完成了物理和虚拟内存管理&#xff0c;这给创建内核线程…

C++之初识STL—vector

文章目录 STL基本概念使用STL的好处容器vector1.vector容器简介2.vector对象的默认构造函数3.vector对象的带参构造函数4.vector的赋值5.vector的大小6.vector容器的访问方式7.vector的插入 STL基本概念 STL(Standard Template Library,标准模板库)STL 从广义上分为: 容器(con…

springboot+vue音乐翻唱与分享平台(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的音乐网站与分享平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;…

基于 FineReport 快速设计联动报表

一、基于 FineReport 快速设计联动报表 FineReport 一款用于报表制作&#xff0c;分析和展示的工具&#xff0c;可以轻松的构建出灵活的数据分析和报表系统。 下面基于 FineReport 自带的数据表 销量 表快速设计一页可视化联动报表&#xff0c;数据格式如下&#xff1a; 报表…

最新最全花1W买的Python+Selenium全栈Web自动化测试

前言&#xff1a;看这篇帖子&#xff0c;最好要在知道定位八大元素的基础之上才能够比较熟练的看完这篇帖子自动化测试是软件开发中非常重要的一环&#xff0c;它可以帮助开发人员提高代码质量、减少错误和缺陷&#xff0c;并节省测试时间。其中&#xff0c;Selenium是一个广泛…

01- 目标检测 (综述)

要点&#xff1a; 区分One-stage detector 和 Two-stage detector 参考链接&#xff1a;深度学习目标检测最全综述 - 爱码网 详细模型解读参考&#xff1a;目标检测简介 - 知乎 一 目标检测分类 1.1 发展历程 检测网络发布历程&#xff1a; 1.2 检测模型分类 2014年后目标…

7---整数反转

给你一个 32 位的有符号整数 x x x &#xff0c;返回将 x x x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31} − 1] [−231,231−1]&#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08…

2017年上半年软件设计师下午试题

试题四 阅读下列说明和 C 代码&#xff0c;回答问题 1 至问题 3&#xff0c;将解答写在答题纸的对应栏内。 【说明】 假币问题&#xff1a;有 n 枚硬币&#xff0c;其中有一枚是假币&#xff0c;己知假币的重量较轻。现只有一个天平&#xff0c;要求用尽量少的比较次数找出这枚…

【编程福音,25款必备AI编码工具推荐,让你事半功倍】

&#x1f680; AI破局先行者 &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#x1f3c6;&am…

代码随想录算法训练营第三十四天 | 加油站题、左右贪心

1005. K次取反后最大化的数组和 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;贪心算法&#xff0c;这不就是常识&#xff1f;还能叫贪心&#xff1f;LeetCode&#xff1a;1005.K次取反后最大化的数组和_哔哩哔哩_bilibili 状态&#xff1a;能做出…

Hadoop的安装与配置

Hadoop的安装与配置 推荐按照我的博客下载hadoop&#xff0c;spark&#xff0c;pyspark以及scala这样版本搭配更好。 如果觉得自己不会版本搭配可私聊博主。 scala的安装和配置&#xff1a;https://blog.csdn.net/weixin_41957626/article/details/130548174 spark的安装和配置…

宇树Unitree机器狗连接外网的一种方法

宇树官方提供的方式&#xff1a; ​​​​​​​ 宇树机器狗连接网络的相关说明 (yuque.com) 我这里提供一种我采用的方式&#xff0c;仅供参考&#xff1a; 需要一根手机数据线&#xff0c;能联网的手机 我这里使用的是小米手机&#xff0c;其余手机大概也能行。 如下&…

ElasticSearch学习随笔之高级检索

ElasticSearch 1、ElasticSearch学习随笔之基础介绍 2、ElasticSearch学习随笔之简单操作 3、ElasticSearch学习随笔之java api 操作 4、ElasticSearch学习随笔之SpringBoot Starter 操作 5、ElasticSearch学习随笔之嵌套操作 6、ElasticSearch学习随笔之分词算法 7、ElasticS…

强化学习_06_pytorch-TD3实践(BipedalWalkerHardcore-v3)

基于策略的离线算法TD3 1.1 简介 reference: openai-TD3 DDPG的critic会高估, 从而导致actor策略失败。TD3是增加了三个关键技巧优化DDPG。经过优化后的TD3(Twin Dalayed DDPG 双延迟深度确定性策略梯度算法)适合于具有高维连续动作空间的任务。 Tricks: Clipped Double Q-l…

github学习笔记

目录 github简介 唯一版本库是什么意思 hub的含义什么&#xff1f; github功能介绍 登录、注册 GitHub 术语解释 Git 初体验及其常用命令介绍 git中的两个分支是否有冲突是什么意思&#xff0c;这是因为什么导致的 利用 SSH 完成 Git 与 GitHub 的绑定 通过 Git 将代…

[ Azure 云计算从业者 | AZ-900 ] Chapter 06 | 认识与了解 Azure 中相关的计算服务

本章节主要内容进行讲解&#xff1a;计算服务中的虚拟机 VM、虚拟机规模集 VMSS、Azure 容器&#xff08;ACI&#xff09;、Azure Kubernetes Service (AKS) 与Azure Functions 本系列已经更新文章列表&#xff08;已更新&#xff09;&#xff1a; [ Azure 云计算从业者 | AZ…