Spring Session & Redis实现Session共享

Spring Session & Redis实现Session共享SpringSession&Redis实现Session共享前后端分离Session、单点登录实现Session共享简单方案,充当笔记一、Session和Cookie1.Session简介:Session及会话,是web开发中得一种会话跟踪技术。Session会话过程:当用户打开浏览器,从第一次请求开始,一直到最终关闭浏览器,就表示一次会话。2.Cookie简介:Cookie是由服务器生成,保存在客户端得一种消息载体。这个载体中存放这用户访问该站点得会话状态消息,只要Cook

Spring Session & Redis实现Session共享

前后端分离Session、单点登录实现 Session 共享简单方案,充当笔记

一、Session和Cookie

1.Session简介:

Session及会话,是web开发中得一种会话跟踪技术。

Session会话过程:当用户打开浏览器,从第一次请求开始,一直到最终关闭浏览器,就表示一次会话。

2.Cookie简介:

Cookie是由服务器生成,保存在客户端得一种消息载体。这个载体中存放这用户访问该站点得会话状态消息,只要Cookie没有被清空或者失效,那么保存中的会话会一直有效。

Cookie过程:用户在第一次请求时,有服务器生成Cookie,并将其封装到请求头中,以响应的形式发送给客户端。客户端将其保存,当客户端再次发送同样的请求后,请求中会携带Cookie发送服务端,服务器对会话进行跟踪。

3.Session和Cookie区别(简单说明)

Session保存在服务端,而Cookie保存在客户端。Session保存在服务端,关闭浏览器,就表示一次会话(session过期),而Cookie只要客户端没有被清空或者失效,那么保存中的会话会一直有效。(注意Cookie包含Session,都是以Cookie的形式存储)

例:
Session 客户端
Session
Cookie
在这里插入图片描述

二、使用Session遇到的问题及场景

1.单个Tomcat时使用Session(单个Tomcat下Session不会出现大问题)

在这里插入图片描述

2.多个Tomcat时使用Session

在这里插入图片描述
看出问题了吗?这样的问题,TomcatB生成Session,访问TomcatA时,TomcatA并不知道TomcatB创建的Session,直接跨域问题或获取JsessionId后get导致返回null;

解决方案有很多:Session 黏连、Session 复制、Session 外部化存储(MySQL、MongoDB、Redis)。

快速入门Spring Session + Redis

前提:虽然Tomcat不一样,但是还是共用Redis的

pom.xml:

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 实现对 Spring MVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 实现对 Spring Session 使用 Redis 作为数据源的自动化配置 -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <!-- 实现对 Spring Data Redis 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 -->
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

application.properties

#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379

拦截器:

/** * @author lanys * @Description: * @date 3/6/2021 上午9:34 */
@Configuration
public class WebSecurityConfig implements WebMvcConfigurer { 
   

    //自定义拦截
    @Bean
    public RedisSessionInterceptor redisSessionInterceptor(){ 
   
        return new RedisSessionInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) { 
   
        //
        registry.addInterceptor(redisSessionInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/user/login");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

自定义拦截:

/** * @author lanys * @Description: * @date 3/6/2021 上午9:36 */

public class RedisSessionInterceptor implements HandlerInterceptor { 
   

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
   

        HttpSession session = request.getSession();
        String id = session.getId();
        Integer loginUserId1 = (Integer) session.getAttribute("loginUserId");
        if (session.getAttribute("loginUserId")!=null){ 
   
           try{ 
   
               String loginUserId= (String) redisTemplate.opsForValue().get("loginUserId:"+loginUserId1);
               if (loginUserId!=null && loginUserId.equals(session.getId())){ 
   
                   return true;
               }
           }catch (Exception e){ 
   
               e.printStackTrace();
           }
        }
        response.getWriter().print( "用户未登录!");
        return false;
    }
}

LoginController:

/** * @author lanys * @Description: * @date 3/6/2021 上午9:46 */
@RestController
@RequestMapping(value = "/api/user")
public class LoginController { 
   


    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("/login")
    public String login(HttpServletRequest request, Integer account, Integer password) throws Exception { 
   

        SysUser sysUser = new SysUser();


        if ( sysUser.getAccount()==account && sysUser.getPassword()==password)
        { 
   
            HttpSession session = request.getSession();
            session.setAttribute("loginUserId", sysUser.getUserId());
            redisTemplate.opsForValue().set("loginUserId:"+sysUser.getUserId(), session.getId());
            return "登录成功";
        }
        else
        { 
   
            throw new Exception("账户名或密码错误!");
        }
    }

    @RequestMapping(value = "/getUserInfo")
    public Object get(long userId) throws Exception { 
   
        SysUser sysUser = new SysUser();

        if ( sysUser.getUserId()==userId)
        { 
   
            return  "查询成功!:"+sysUser.getUserId();
        }
        else
        { 
   
            throw new Exception( "用户不存在!");
        }
    }
}

SysUser:

/** * @author lanys * @Description: * @date 3/6/2021 上午9:47 */

@Data
public class SysUser { 
   

    private int UserId=123456;

    private int account=123;

    private int password=123;

}

RedisSession:

/** * @author lanys * @Description: 开启自动化配置 Spring Session 使用 Redis 作为数据源 * maxInactiveIntervalInSeconds=30 30秒后过期 * @date 3/6/2021 上午11:07 */
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30)
@Configuration
public class RedisSession { 
   

       @Bean
       public static ConfigureRedisAction configureRedisAction(){ 
   
           return ConfigureRedisAction.NO_OP;
       }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
30秒后,过期了,查询不到数据(修改时间 RedisSession 类)
在这里插入图片描述

总结

该只是例子,主要充当思想,遇到了知道该怎么解决,有什么方案,文章结合网上其他博主的文章充当自己笔记。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/28187.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注