美文网首页三月听我说
SpringSecurity + Redis + 分布式缓存 踩

SpringSecurity + Redis + 分布式缓存 踩

作者: STioPlato | 来源:发表于2020-05-09 10:19 被阅读0次

    SpringSecurity5.x

    这个东西上次搞的时候是2个月前,第一次弄是真的摸不到头脑,看着那么厉害的视频都没懂,然后生病了,就没再弄。这次运气好点,终于看懂了。

    可能是受Laravel用户登录管理模块的影响,一开始我实在是搞不清楚SpringSecurity的config配置模式,就那种http.formLogin.......一堆链式调用的方式,看着实在是奇怪,并且深信一定会有其它方式来代替这种配置方式,毕竟这么写总给人感觉不够优雅。然而我还是妥协了。在Laravel中我记得是只需要把sql文件导入一下,然后只需要打开某个接口还是配置文件就可以了。尽管Laravel的如此简单,我当时弄的时候还是摸不着头脑地把源码差不多翻了几天,谁知道到最后只需要打开一句代码的注释就好了。艹。

    说回SpringSecurity,http.formLogin之后的配置可谓是多种多样,我只需要链式调用4、5次,然后再实现了几个接口就可以配置出来简单的前后台分离的用户认证模块了。在这里我粘贴出来自己的一些配置和类吧,给大家提供一个参考。

    http
                    //添加验证码过滤器
                    .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                    .formLogin()
                    //如果没有登录,则会自动跳到这个接口
                    .loginPage("/authentication/require")
                    //执行登录的接口
                    .loginProcessingUrl("/login")
                    //执行成功的处理器
                    .successHandler(userAuthenticationSuccessHandler)
                    //执行失败的处理器
                    .failureHandler(userAuthenticationFailureHandler)
                    .and()
                    //下方是url权限控制
                    .authorizeRequests()
                    //指定url,放行
                    .antMatchers("/authentication/require","/login").permitAll()
                    //任意url
    //                .anyRequest()
    //                //需要认证
    //                .authenticated()
                    //关闭csrf以允许Druid
                    .and().csrf().disable();
    

    具体的注释我都标上了。其中的successHandler和FailureHandler就是自己实现的两个成功和失败时候的处理的接口,代码比较简单。

    /**
     * @author shenyvhao
     * @program OnlineForm
     * @description
     * @create 2020-05-08 11
     **/
    @Component("userAuthenticationFailureHandler")
    public class UserAuthenticationFailureHandler implements AuthenticationFailureHandler {
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Override
        public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
    
            //登录失败的处理
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(6,e.getMessage())));
    
        }
    }
    
    
    /**
     * @author shenyvhao
     * @program OnlineForm
     * @description
     * @create 2020-05-08 11
     **/
    
    @Component("userAuthenticationSuccessHandler")
    public class UserAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(JsonResult.success(authentication)));
        }
    }
    
    

    然后是连接Redis写验证码,遇见了坑,基础问题搞了我将近两个小时。具体的问题就是 我在获取验证码的接口上把验证码存入了Reids里面,但是在验证吗的过滤器中死活取不到验证码的值,一开始一直以为是Redis的问题,因为Redis在存的时候可能会把数据序列化一下,key前面会加上一些字符什么之类的,然后我就换成了StringRedisTemplate,然后发现还是不行。我思来想去,难不成是Java里面默认用的redis数据库和存的时候的数据库不一样??现在想想好蠢哈哈哈,存的时候都已经用到默认的库了。后来在我就检查redis里面的所有key都有什么,谁知道sout set.size()的时候就报空指针了,后来恍然大悟,原来是Bean压根没有注入到filter里面。

    后来查到说是Web容器的加载顺序是 listener--filter--servlet,怪不得。然后我就new 了一个filter通过setter给他把需要用到的bean给set了进去,就可以使用了。

    然后是想着用Redis管理Session,实现一下分布式Session。

    pom

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
            <!--        Spring Session-->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <version>2.1.8.RELEASE</version>
    

    但是怎么操作呢。。就想到了以前一开始写项目的时候贪心加入了好多依赖,什么都不会的时候加入Spring-data-redis, spring-session 什么之类的,这时候项目启动起来是会报错的,大概是redis连接不上,session没办法存。然后我当时的解决办法是在yml文件里面把session的存储类型改成了none,也就是:

      session:
        store-type: none
    

    后来我在配置文件中发现了这个,把none删了,刚一输入字母r,就出来redis了,哈哈哈哈哈哈,看来是只需要配置这一下差不多就可以了。后来项目跑起来,确实也没报错,可是我怎么知道redis里面有没有东西呢。。然后就去redis里面看,登录接口调用之后,keys * 看到了多出来了几个键值对,哈哈哈那这就是成功了吧。

    后来还是不甘心,感觉不够确认。就又下载可视化工具查看了一下redis里面具体的数据结构,嗯,这下应该安心了。


    redis中看到的session

    相关文章

      网友评论

        本文标题:SpringSecurity + Redis + 分布式缓存 踩

        本文链接:https://www.haomeiwen.com/subject/bvehnhtx.html