千家信息网

Redis如何快速实现分布式session

发表于:2024-11-12 作者:千家信息网编辑
千家信息网最后更新 2024年11月12日,这篇文章主要为大家展示了"Redis如何快速实现分布式session",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Redis如何快速实现分布式sessio
千家信息网最后更新 2024年11月12日Redis如何快速实现分布式session

这篇文章主要为大家展示了"Redis如何快速实现分布式session",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Redis如何快速实现分布式session"这篇文章吧。

前言

我们在开发一个项目时通常需要登录认证,常用的登录认证技术实现框架有Spring Security和shiro

Spring Security

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于spring的应用程序的事实上的标准。

Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正强大之处在于它可以很容易地扩展以满足定制需求,并且Spring Security和spring更加适配贴合,我们工作中常常使用到Spring Security。

Apache Shiro

Apache Shiro 是 Java 的一个安全框架。目前,使用 Apache Shiro 的人越来越多,因为它相当简单,对比Spring Security,可能没有 Spring Security 做的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的 Shiro 就足够了。

不足:

这些都是认证技术框架,在单体应用中都是常用的技术框架,但是在分布式中,应用可能要部署多份,这时通过nginx分发请求,但是每个单体应用都要可能重复验证,因为他们的seesion数据是放在他们自己服务中的。

Session作用

Session是客户端与服务器通讯会话跟踪技术,服务器与客户端保持整个通讯的会话基本信息。

客户端在第一次访问服务端的时候,服务端会响应一个sessionId并且将它存入到本地cookie中,在之后的访问会将cookie中的sessionId放入到请求头中去访问服务器。

spring-session

Spring Session是Spring的项目之一,Spring Session把servlet容器实现的httpSession替换为spring-session,专注于解决session管理问题。

Spring Session提供了集群Session(Clustered Sessions)功能,默认采用外置的Redis来存储Session数据,以此来解决Session共享的问题。

spring-session提供对用户session管理的一系列api和实现。提供了很多可扩展、透明的封装方式用于管理httpSession/WebSocket的处理。

支持功能

  1. 轻易把session存储到第三方存储容器,框架提供了redis、jvm的map、mongo、gemfire、hazelcast、jdbc等多种存储session的容器的方式。这样可以独立于应用服务器的方式提供高质量的集群。

  2. 同一个浏览器同一个网站,支持多个session问题。 从而能够很容易地构建更加丰富的终端用户体验。

  3. Restful API,不依赖于cookie。可通过header来传递jessionID 。控制session id如何在客户端和服务器之间进行交换,这样的话就能很容易地编写Restful API,因为它可以从HTTP 头信息中获取session id,而不必再依赖于cookie

  4. WebSocket和spring-session结合,同步生命周期管理。当用户使用WebSocket发送请求的时候

分布式seesion实战

步骤1:依赖包

因为是web应用。我们加入springboot的常用依赖包web,加入SpringSession、redis的依赖包,移支持把session存储在redis

    org.springframework.boot    spring-boot-starter-web    org.springframework.boot    spring-boot-starter-test    test    org.projectlombok    lombok    1.18.8    org.springframework.boot    spring-boot-starter-redis    1.4.7.RELEASE    org.springframework.session    spring-session-data-redis

这里因为是把seesion存储在redis,这样每个服务登录都是去查看redis中数据进行验证的,所有是分布式的。 这里要引入spring-session-data-redis和spring-boot-starter-redis

步骤2:配置文件

spring.application.name=spring-boot-redisserver.port=9090# 设置session的存储方式,采用redis存储spring.session.store-type=redis# session有效时长为15分钟server.servlet.session.timeout=PT15M## Redis 配置## Redis数据库索引spring.redis.database=1## Redis服务器地址spring.redis.host=127.0.0.1## Redis服务器连接端口spring.redis.port=6379## Redis服务器连接密码(默认为空)spring.redis.password=

步骤3:实现逻辑

初始化用户数据

@Slf4j@RestController@RequestMapping(value = "/user")public class UserController {    Map userMap = new HashMap<>();    public UserController() {        //初始化1个用户,用于模拟登录        User u1=new User(1,"user1","user1");        userMap.put("user1",u1);    }}

这里就不用使用数据库了,初始化两条数据代替数据库,用于模拟登录

登录

 @GetMapping(value = "/login")    public String login(String username, String password, HttpSession session) {        //模拟数据库的查找        User user = this.userMap.get(username);        if (user != null) {            if (!password.equals(user.getPassword())) {                return "用户名或密码错误!!!";            } else {                session.setAttribute(session.getId(), user);                log.info("登录成功{}",user);            }        } else {            return "用户名或密码错误!!!";        }        return "登录成功!!!";    }

登录接口,根据用户名和密码登录,这里进行验证,如果验证登录成功,使用 session.setAttribute(session.getId(), user);把相关信息放到session中。

查找用户

    /**     * 通过用户名查找用户     */    @GetMapping(value = "/find/{username}")    public User find(@PathVariable String username) {        User user=this.userMap.get(username);        log.info("通过用户名={},查找出用户{}",username,user);        return user;    }

模拟通过用户名查找用户

获取session

  /**     *拿当前用户的session     */    @GetMapping(value = "/session")    public String session(HttpSession session) {        log.info("当前用户的session={}",session.getId());        return session.getId();    }

退出登录

  /**     * 退出登录     */    @GetMapping(value = "/logout")    public String logout(HttpSession session) {        log.info("退出登录session={}",session.getId());        session.removeAttribute(session.getId());        return "成功退出!!";    }

这里退出时,要把session中的用户信息删除。

步骤4:编写session拦截器

session拦截器的作用:验证当前用户发来的请求是否有携带sessionid,如果没有携带,提示用户重新登录。

 @Configuration    public class SecurityInterceptor implements HandlerInterceptor {        @Override        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {            HttpSession session = request.getSession();            //验证当前session是否存在,存在返回true true代表能正常处理业务逻辑            if (session.getAttribute(session.getId()) != null){                log.info("session拦截器,session={},验证通过",session.getId());                return true;            }            //session不存在,返回false,并提示请重新登录。            response.setCharacterEncoding("UTF-8");            response.setContentType("application/json; charset=utf-8");            response.getWriter().write("请登录!!!!!");            log.info("session拦截器,session={},验证失败",session.getId());            return false;        }    }

步骤5:把拦截器注入到拦截器链中

@Slf4j@Configurationpublic class SessionCofig implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new SecurityInterceptor())                //排除拦截的2个路径                .excludePathPatterns("/user/login")                .excludePathPatterns("/user/logout")                //拦截所有URL路径                .addPathPatterns("/**");    }}

步骤6:测试

登录user1用户:http://127.0.0.1:9090/user/login?username=user1&password=user1

查询user1用户session:http://127.0.0.1:9090/user/session

退出登录: http://127.0.0.1:9090/user/logout

登录后查看redis中数据:

seesion数据已经保存到redis了,到这里我们就整合了使用spring-seesion实现分布式seesion功能。

以上是"Redis如何快速实现分布式session"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0