当前位置: 首页 > news >正文

(Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五

首先,导包。

在pom.xml文件里面加入以下:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.session</groupId>
   <artifactId>spring-session-data-redis</artifactId>
</dependency>

jar包不做多解释了,看那个artifactId的内容应该能知道干啥的。

然后是yml文件:

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password:
    jedis.pool.max-idle: 100
    jedis.pool.max-wait: -1ms
    jedis.pool.min-idle: 2
    timeout: 2000ms

是的,很精简。

然后是,到你的RedisConfig文件上面,开启redis的session关联注解(其实不用这个注解也是没问题的,后面自己可以去除看看。)

@EnableRedisHttpSession(maxInactiveIntervalInSeconds=60) 这边是设置存入redis里面的值的过期时间。

默认不设置的话,是1800秒即30分钟。

@EnableRedisHttpSession

如:

OK,我们开始共享session咯!

在controller文件里面写2个方法吧,

@GetMapping("/setSessionValue")
public String setredisResult(HttpServletRequest request){
    request.getSession().setAttribute(request.getSession().getId(), "---测试数据---"+request.getRequestURL());

    System.out.println(request.getSession().getId());
    return "set成功,已经存入session域且redis里面也会有值";
}

@GetMapping("/getSessionValue")
public String redisResult(HttpServletRequest request) {
    System.out.println(request.getSession().getId());
    String value = String.valueOf(request.getSession().getAttribute(request.getSession().getId()));
    
    return "取值成功         :"+value;
}

先运行第一个, 如下:

控制台打印出sessionid值:

 

然后再瞟一眼redis数据库,是的,没错,可以看到redis也存储了这个session会话的相关信息。 (TTL是过期时间)

 

然后访问下第二个接口,可以看到根据sessionid作为Key去session域是能正常获取值的,

 

好了,redis实现session共享到此其实已经完毕了!

有人可能会有疑问,怎么体现共享了? 这时候,你如果实现负载均衡,开启两个tomcat服务器,不同端口,然后用通过浏览器通过不同端口去访问,你会发现,通过request.getSession().getId()拿出来的sessionid是一样一样的!

 

那么接下来简单介绍下,使用这个唯一id来实现单点登录:




    @GetMapping("/userLogin")
    public String setRedisResult(HttpServletRequest request){

        //第一次登录

        //1. 取出当期客户端的sessionId
        String sId=request.getSession().getId();
        //2. 查询该sessionId 是否存在于redis
        boolean exists = redisUtils.exists(sId);

        if (!exists){
            //2.1未登录过,进行用户信息的校验
            //如果通过后,写入session域进行共享,即使是负载不同端口,sessionId不会发生变化
            request.getSession().setAttribute(sId, "login success");
            redisUtils.setWithTime(sId,"login success",1000);
            return "success login!";

            //如果不通过,那么返回登录页面,省略
        }else {
            //2.2 已经登录过,则存入redis中刷新过期时间,再直接返回成功页面
            redisUtils.setWithTime(sId,"login success",1000);
            return " yes,you are allow!";
        }

    }

    @GetMapping("/userLoginOut")
    public String userLoginOut(HttpServletRequest request){

        String sId=request.getSession().getId();
        redisUtils.remove(sId);
        return "login out!";
    }

ps:代码里使用到的工具类RedisUtils 在这:https://blog.csdn.net/qq_35387940/article/details/94392100

 

可以看到以上情况其实单纯使用redis配合sesionid共享后就能完成单点登录;

题外补充:
但是以上这种情况是使用上了redis的session共享,保证了sessionId不变,所以每次去出来,在有效时间内都是一样的。
既然都讲到了单点登录吗,那么如果单纯使用redis不使用session共享怎么去实现呢?那就是将第一次登录的sessionId保存在浏览器cookise里,这样每次登录通过cookise去拿出头一次固定不变的sessionid,来判断用户是否有登录过。
这种思路实现方案是:

  //登录接口
    @GetMapping("/userLogin")
    public String setRedisResult(HttpServletRequest request, HttpServletResponse response){
        
        //第一次登录

        //1. 取出当期客户端的sessionId
        String sId=request.getSession().getId();

        String cookies = getCookies(request);

        if (cookies==null || cookies.equals("")){

            System.out.println("没有登录过,准备进行登录!");
            //执行登录逻辑

            //写入cookie
            writeLoginToken(response,sId); //这里设置cookie的过期时间应当与redis设置的时间且与session失效时间保持一致
            //写入redis
            redisUtils.setWithTime(sId,"userInfo",1000);
            System.out.println("登录成功!");
            return "success login!";
        }else{

            boolean exists = redisUtils.exists(cookies);
            if (exists){

                System.out.println("已经登录过,正常登录!");
                return " yes,you are allow!";
            }else {

                return "信息异常不允许登录";
            }
        }



    }
 /**
     * 获取浏览器存入
     * @param request
     * @return
     */
    public  String getCookies(HttpServletRequest request){
        //HttpServletRequest 装请求信息类
        //HttpServletRespionse 装相应信息的类

        Cookie[] cookies =  request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                if(cookie.getName().equals("SESSION_ID")){
                    return cookie.getValue();
                }
            }
        }

        return  null;
    }

    /**
     *设置浏览器cookie
     * @param response
     * @param token
     */
    public static void writeLoginToken(HttpServletResponse response,String token){
        Cookie ck = new  Cookie("SESSION_ID",token);
        //设置cookie的域
//        ck.setDomain("jc.test.com");
//        //代表设在根目录
//        ck.setPath("/");
        //防止脚本读取
        ck.setHttpOnly(true);
        //单位是秒,设置成-1代表永久,如果cookie不设置maxage的话,cookie就不会写入硬盘,写在内存中,只在当前页面有效
        ck.setMaxAge(1000);
        response.addCookie(ck);
    }

 

就到此吧。

 

相关文章:

  • 什么是Kafka
  • Springboot 线程同步之Semaphore 的简单使用
  • JAVA Gson的使用
  • JAVA 最全最细的fastjson使用介绍,带你透彻领悟JSON
  • fastJson注解@JSONField 的作用及其效果
  • HttpClient 不同版本的超时时间设置
  • 使用两个栈实现队列,简单例子
  • 数据库ACID
  • 线程小记
  • JAVA JDK1.8 时间戳与时间格式化 实用工具类
  • 单例模式 之内部类延迟加载,(多)线程安全
  • Springboot 用session监听器统计在线用户数量
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • JAVA 责任链设计模式
  • JAVA回调函数简单讲解 CallBack
  • 《Java编程思想》读书笔记-对象导论
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 78. Subsets
  • es6(二):字符串的扩展
  • IP路由与转发
  • js作用域和this的理解
  • Linux链接文件
  • nodejs实现webservice问题总结
  • Python 基础起步 (十) 什么叫函数?
  • python学习笔记 - ThreadLocal
  • vue数据传递--我有特殊的实现技巧
  • 构建二叉树进行数值数组的去重及优化
  • 实习面试笔记
  • 7行Python代码的人脸识别
  • Mac 上flink的安装与启动
  • 阿里云ACE认证学习知识点梳理
  • ​香农与信息论三大定律
  • #mysql 8.0 踩坑日记
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (LeetCode 49)Anagrams
  • (五)IO流之ByteArrayInput/OutputStream
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)Google的Objective-C编码规范
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • .gitignore文件设置了忽略但不生效
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net 设置默认首页
  • .net 无限分类
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET企业级应用架构设计系列之技术选型
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .NET中统一的存储过程调用方法(收藏)
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @JsonSerialize注解的使用