文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot+SpringSession+Redis怎么实现session共享

2023-06-14 22:19

关注

这篇文章主要介绍SpringBoot+SpringSession+Redis怎么实现session共享,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

springboot是什么

springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。

一、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>

二、application.properties的redis配置

#redisspring.redis.host=127.0.0.1spring.redis.port=6379spring.redis.password=123456spring.redis.pool.max-idle=8spring.redis.pool.min-idle=0spring.redis.pool.max-active=8spring.redis.pool.max-wait=-1#超时一定要大于0spring.redis.timeout=3000spring.session.store-type=redis

在配置redis时需要确保redis安装正确,并且配置notify-keyspace-events Egx,spring.redis.timeout设置为大于0,我当时这里配置为0时springboot时启不起来。

三、编写登录状态拦截器RedisSessionInterceptor

//拦截登录失效的请求public class RedisSessionInterceptor implements HandlerInterceptor{    @Autowired    private StringRedisTemplate redisTemplate;     @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception    {        //无论访问的地址是不是正确的,都进行登录验证,登录成功后的访问再进行分发,404的访问自然会进入到错误控制器中        HttpSession session = request.getSession();        if (session.getAttribute("loginUserId") != null)        {            try            {                //验证当前请求的session是否是已登录的session                String loginSessionId = redisTemplate.opsForValue().get("loginUser:" + (long) session.getAttribute("loginUserId"));                if (loginSessionId != null && loginSessionId.equals(session.getId()))                {                    return true;                }            }            catch (Exception e)            {                e.printStackTrace();            }        }         response401(response);        return false;    }     private void response401(HttpServletResponse response)    {        response.setCharacterEncoding("UTF-8");        response.setContentType("application/json; charset=utf-8");         try        {            response.getWriter().print(JSON.toJSONString(new ReturnData(StatusCode.NEED_LOGIN, "", "用户未登录!")));        }        catch (IOException e)        {            e.printStackTrace();        }    }     @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception    {     }     @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception    {     }}

四、配置拦截器

@Configurationpublic class WebSecurityConfig extends WebMvcConfigurerAdapter{    @Bean    public RedisSessionInterceptor getSessionInterceptor()    {        return new RedisSessionInterceptor();    }     @Override    public void addInterceptors(InterceptorRegistry registry)    {        //所有已api开头的访问都要进入RedisSessionInterceptor拦截器进行登录验证,并排除login接口(全路径)。必须写成链式,分别设置的话会创建多个拦截器。        //必须写成getSessionInterceptor(),否则SessionInterceptor中的@Autowired会无效        registry.addInterceptor(getSessionInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/user/login");        super.addInterceptors(registry);    }}

五、登录控制器

@RestController@RequestMapping(value = "/api/user")public class LoginController{    @Autowired    private UserService userService;     @Autowired    private StringRedisTemplate redisTemplate;     @RequestMapping("/login")    public ReturnData login(HttpServletRequest request, String account, String password)    {        User user = userService.findUserByAccountAndPassword(account, password);        if (user != null)        {            HttpSession session = request.getSession();            session.setAttribute("loginUserId", user.getUserId());            redisTemplate.opsForValue().set("loginUser:" + user.getUserId(), session.getId());             return new ReturnData(StatusCode.REQUEST_SUCCESS, user, "登录成功!");        }        else        {            throw new MyException(StatusCode.ACCOUNT_OR_PASSWORD_ERROR, "账户名或密码错误!");        }    }     @RequestMapping(value = "/getUserInfo")    public ReturnData get(long userId)    {        User user = userService.findUserByUserId(userId);        if (user != null)        {            return new ReturnData(StatusCode.REQUEST_SUCCESS, user, "查询成功!");        }        else        {            throw new MyException(StatusCode.USER_NOT_EXIST, "用户不存在!");        }    }}

六、效果

我在浏览器上登录,然后获取用户信息,再在postman上登录相同的账号,浏览器再获取用户信息,就会提示401错误了,浏览器需要重新登录才能获取得到用户信息,同样,postman上登录的账号就失效了。

浏览器:

SpringBoot+SpringSession+Redis怎么实现session共享

SpringBoot+SpringSession+Redis怎么实现session共享

postman:

SpringBoot+SpringSession+Redis怎么实现session共享

七、核心原理详解

分布式session需要解决两个难点:1、正确配置redis让springboot把session托管到redis服务器。2、唯一登录。

1、redis:

redis需要能正确启动到出现如下效果才证明redis正常配置并启动

SpringBoot+SpringSession+Redis怎么实现session共享

同时还要保证配置正确

@EnableCaching@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30)//session过期时间(秒)@Configurationpublic class RedisSessionConfig{    @Bean    public static ConfigureRedisAction configureRedisAction()    {        //让springSession不再执行config命令        return ConfigureRedisAction.NO_OP;    }}

springboot启动后能在redis上查到缓存的session才能说明整个redis+springboot配置成功!

SpringBoot+SpringSession+Redis怎么实现session共享

2、唯一登录:

用户登录时,在redis中记录该userId对应的sessionId,并将userId保存到session中。

HttpSession session = request.getSession();session.setAttribute("loginUserId", user.getUserId());redisTemplate.opsForValue().set("loginUser:" + user.getUserId(), session.getId());

访问接口时,会在RedisSessionInterceptor拦截器中的preHandle()中捕获,然后根据该请求发起者的session中保存的userId去redis查当前已登录的sessionId,若查到的sessionId与访问者的sessionId相等,那么说明请求合法,放行。否则抛出401异常给全局异常捕获器去返回给客户端401状态。

以上是“SpringBoot+SpringSession+Redis怎么实现session共享”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯