阅读 313

SpringSecurity+Redis认证过程小结

这篇文章主要介绍了SpringSecurity+Redis认证过程小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

目录
  • 前言引入

  • Security的核心配置文件

  • Security的认证过程

    • 1. 是登录请求

    • 2. 不是登录请求

  • 使用Redis整合时的注意事项

    由于今天用Security进行权限管理的时候出现了一些Bug,特此发这篇博客来补习一下对SpringSecurity的理解

    前言引入

    当今市面上用于权限管理的流行的技术栈组合是

    • ssm+shrio

    • SpringCloud+SpringBoot+SpringSecurity

    这种搭配自然有其搭配的特点,由于SpringBoot的自动注入配置原理,在创建项目时就自动注入管理SpringSecurity的过滤器容器(DelegatingFilterProxy),而这个过滤器是整个SpringSercurity的核心。掌握着SpringSercurity整个权限认证过程,而SpringBoot很香的帮你将其自动注入了,而用ssm
    去整合Security,将会耗用大量的配置文件,不易于开发,而Security的微服务权限方案,更是能和Cloud完美融合,于是Security比Shrio更强大,功能更齐全。

    Security的核心配置文件

    核心:Class SecurityConfig extends WebSecurityConfigurerAdapter

    继承了WebSecurityConfigurerAdapter后我们关注于configure方法对于在整个安全认证的过程进行相关的配置,当然在配置之前我们先简单了解一下流程

    简单的看了整个权限认证的流程,很轻易的总结得出,SpringSecurity核心的就是以下几种配置项了

    • 拦截器(Interceptor)

    • 过滤器(Filter)

    • 处理器(Handler,异常处理器,登录成功处理器)

    那我们就首先通过配置来完成认证过程吧!!!!

    Security的认证过程

    假设我们要实现一下的认证功能


    1. 是登录请求

    • 我们需要先判断验证码是否正确(验证码过滤器,通过addFilerbefore实现前置拦截)

    • 再判断用户名密码是否正确(使用自带的用户名密码过滤器,UsernamePasswordAuthenticationFilter

    • 配置异常处理器(Handler)通过IO流将异常信息写出

    关于密码校验的流程:
    UsernamePasswordAuthenticationFilter的密码校验规则是基于AuthenticationManagerBuilder(认证管理器)下的 UserDetailsService里的规则进行验证的:
    其中的核心方法:

    1.public UserDetails *loadUserByUsername(String username)
    通过请求参数的用户名去数据库查询是否存在,存在则将其封装在UserDetails里面,而验证过程是通过AuthenticationManagerBuilder获取到UserDetail里的username和password来校验的,
    这样我们就可以通过

    • 配置yaml文件设置账号密码

    • 通过数据库结合UserDetail来设置账号密码

    (UserDetailsService中的方法,注意需要将UserDetailsService注入AuthenticationManagerBuilder中)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getByUsername(username);
        if (sysUser == null) {
            throw new UsernameNotFoundException("用户名或密码不正确");
        }
        // 注意匹配参数,前者是明文后者是暗纹
        System.out.println("是否正确"+bCryptPasswordEncoder.matches("111111",sysUser.getPassword()));
        return new AccountUser(sysUser.getId(), sysUser.getUsername(), sysUser.getPassword(), getUserAuthority(sysUser.getId()));
    }

    通过了这个验证后,过滤器放行,不通过就用自定义或者默认的处理器处理

    核心配置文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    package com.markerhub.config;
     
    import com.markerhub.security.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
     
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
     
        @Autowired
        LoginFailureHandler loginFailureHandler;
     
        @Autowired
        LoginSuccessHandler loginSuccessHandler;
     
        @Autowired
        CaptchaFilter captchaFilter;
     
        @Autowired
        JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
     
        @Autowired
        JwtAccessDeniedHandler jwtAccessDeniedHandler;
     
        @Autowired
        UserDetailServiceImpl userDetailService;
     
        @Autowired
        JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
     
        @Bean
        JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
            JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
            return jwtAuthenticationFilter;
        }
     
        @Bean
        BCryptPasswordEncoder bCryptPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
     
        private static final String[] URL_WHITELIST = {
     
                "/login",
                "/logout",
                "/captcha",
                "/favicon.ico",
     
        };
     
     
        protected void configure(HttpSecurity http) throws Exception {
     
            http.cors().and().csrf().disable()
     
                    // 登录配置
                    .formLogin()
                    .successHandler(loginSuccessHandler)
                    .failureHandler(loginFailureHandler)
     
                    .and()
                    .logout()
                    .logoutSuccessHandler(jwtLogoutSuccessHandler)
     
                    // 禁用session
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
     
                    // 配置拦截规则
                    .and()
                    .authorizeRequests()
                    .antMatchers(URL_WHITELIST).permitAll()
                    .anyRequest().authenticated()
     
                    // 异常处理器
                    .and()
                    .exceptionHandling()
                    .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                    .accessDeniedHandler(jwtAccessDeniedHandler)
     
                    // 配置自定义的过滤器
                    .and()
                    .addFilter(jwtAuthenticationFilter())
                    .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
     
            ;
     
        }
     
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailService);
        }
    }

    2. 不是登录请求

    • 通过JwtfFilter来查看是否为登录状态

    使用Redis整合时的注意事项

    本质上还是编写过滤器链:

    • 在登录请求前添加过滤器

    • 注意验证码存储在redis的失效时间,如果超过失效时间将会被验证码拦截器拦截下来

    • 需要准备一个生成验证码的接口,存储在Redis中

    • 使用完验证码需要将其删除

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 校验验证码逻辑
        private void validate(HttpServletRequest httpServletRequest) {
     
            String code = httpServletRequest.getParameter("code");
            String key = httpServletRequest.getParameter("token");
     
            if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
                System.out.println("验证码校验失败2");
                throw new CaptchaException("验证码错误");
            }
     
            System.out.println("验证码:"+redisUtil.hget(Const.CAPTCHA_KEY, key));
            if (!code.equals(redisUtil.hget(Const.CAPTCHA_KEY, key))) {
                System.out.println("验证码校验失败3");
                throw new CaptchaException("验证码错误");
            }
     
            // 一次性使用
            redisUtil.hdel(Const.CAPTCHA_KEY, key);
        }

    到此这篇关于SpringSecurity+Redis认证过程总结的文章就介绍到这了

    原文链接:https://blog.csdn.net/qq_51131591/article/details/122308675


    文章分类
    代码人生
    版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
    相关推荐