【Spring Security OAuth2】- spring security -短信登录配置及重构

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

短信登录配置及重构

重构思路:

  1. 重构不是更改已有的功能

  2. 重构是不影响已有功能的情况下,对已有代码进行抽象封装

  3. 多处使用相同代码的地方,需要抽出来

  4. 比如上章节的很多代码,

    如:图形验证码过滤器和短信验证码过滤器重复代码太多
    服务接口的url地址和过滤器中的过滤器地址重复
    等..

系统配置相关的代码结构

core项目中的重构如下:

  • 密码登录的配置代码
  • 短信登录的配置代码
  • 验证码相关的配置代码

browser项目:

  • BrowserSecurityConfig

  • 只留下浏览器特有的配置代码

    • 如记住我的功能,只有浏览器特有这样的功能

app:

  • AppSecurityConfig
  • App特有的配置代码

通过配置apply功能进行配置的引用

202306181903044231.png

感受

花了6个小时看老师重构之后的代码,然后完成了自己跟练的项目代码;

太厉害!!这个重构技巧太牛逼了;

总之:当有两处重复代码的时候 就要抽取代码了。这个需要大量的经验才能不分类好,不至于越抽越乱

这里再啰嗦下:
关于用户名密码登录和短信登录表单提交的url地址,不需要真实存在,
因为这个是提供这两个特定过滤器框架特定的拦截点。只有提交到指定的拦截点,
才会进入认证功能服务

此次重构一些知识点

  • 善用 HttpSecurity.apply 应用分离之后的配置类
  • 程序中有手动写字符串2次的就抽成 SecurityConstants 常量接口类
  • 善用 Autowired注解提供的 依赖查找功能
  • 善用 类名统一起名
  • 善用枚举类 提供相应的支持

善用 HttpSecurity.apply 应用分离之后的配置类

     HttpSecurity.apply 方法跟踪进来是父类的;这里是一个泛型,所有需要看HttpSecurity对应传递的是什么类型
    public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
            extends AbstractSecurityBuilder<O> {
          public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
            throws Exception {
            configurer.addObjectPostProcessor(objectPostProcessor);
            configurer.setBuilder((B) this);
            add(configurer);
            return configurer;
          }
    
    --------- HttpSecurity 声明
    public final class HttpSecurity extends
            AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
            implements SecurityBuilder<DefaultSecurityFilterChain>,
            HttpSecurityBuilder<HttpSecurity> {
    
    ------------ 注意看对比
    public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer
    
    AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
    
    这里的c对应的泛型就是 <O, B> ,而O,B对应到HttpSecurity的声明就是<DefaultSecurityFilterChain, HttpSecurity>
    
    HttpSecurity.apply 返回一个SecurityConfigurerAdapter<O, B>,所以这里只要继承该类,就是apply需要的对象了
    
    ------------- 如下示例
    /**
     * 验证码配置
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/5 20:05
     */
    @Component
    public class ValidateCodeSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
        /**
         * @see ValidateCodeFilter  目前融合了短信和图形验证码的验证功能
         */
        @Autowired
        private Filter validateCodeFilter;
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // 由源码得知,在最前面的是UsernamePasswordAuthenticationFilter
            http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }

SecurityConstants 常量接口类

在重构中就已经发现这样做的好处了。因为这个代码被分离写和配置的,老是忘记在哪些地方用过
在修改的时候经常忘记修改,或则找不到,所以需要抽成常量类

    public interface SecurityConstants {
    
        /**
         * 默认的处理验证码的url前缀
         */
        public static final String DEFAULT_VALIDATE_CODE_URL_PREFIX = "/code";

善用 Autowired注解提供的 依赖查找功能

把多个实现类统一管理,特别是使用模板方法抽取公用逻辑的时候,就拍上用处了
如下代码,还提供了按beanName查找指定的子类实现;
还提供了按自定义类型,下面会讲到善用命名会在某些地方起到奇效

    /**
     * 处理器持有者,用来管理所有验证码类型的处理器
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/5 20:40
     */
    @Component
    public class ValidateCodeProcessorHolder {
        @Autowired
        private Map<String, ValidateCodeProcessor> validateCodeProcessors;
    
        public ValidateCodeProcessor findValidateCodeProcessor(ValidateCodeType type) {
            return findValidateCodeProcessor(type.toString().toLowerCase());
        }
    
        public ValidateCodeProcessor findValidateCodeProcessor(String type) {
            String beanName = type.toLowerCase() + ValidateCodeProcessor.class.getSimpleName();
            ValidateCodeProcessor processor = validateCodeProcessors.get(beanName);
            if (processor == null) {
                throw new ValidateCodeException("验证码处理器 " + beanName + " 不存在");
            }
            return processor;
        }
    }

善用 类名统一起名

如这里的几个类

  • ValidateCodeProcessor 验证码处理接口
  • ImageValidateCodeProcessor 图片验证码处理接口
  • SmsValidateCodeProcessor 短信验证码处理接口

这里的前缀,配合上面的技巧 善用 Autowired注解提供的 依赖查找功能,使用以下代码就能方便的获取到对应的处理器

    他们都一个共同的父类,有公用的步骤,变化的部分由子类实现;
    public abstract class AbstractValidateCodeProcessor<C extends ValidateCode> implements ValidateCodeProcessor {
      /**
       * 根据请求的url获取校验码的类型:
       * ValidateCodeProcessorHolder : 中持有所有本类的子类型,获取getClass能拿到具体的实例类名
       * @return
       * @see ValidateCodeProcessorHolder
       */
      private ValidateCodeType getValidateCodeType() {
          // 处理器 命名规则:ImageValidateCodeProcessor,拿到前缀即可
          // 返回 Image
          String type = StringUtils.substringBefore(getClass().getSimpleName(), ValidateCodeProcessor.class.getSimpleName());
          return ValidateCodeType.valueOf(type.toUpperCase());
      }
    }
    
    在外部使用 type + ValidateCodeProcessor.class.getSimpleName() 就能获取到完整的类名,
    也就能使用ValidateCodeProcessorHolder动态的获取处理器了

善用枚举类提供相应的支持

枚举类的名称是 短信和图片验证功能的前缀。配合上面的几条。
在使用模板方法模式抽取公用逻辑的时候,可以使用前缀获取不同功能支持的动态常量等类容
在外部要动态使用服务的时候,也能用前缀+具体的的父类命名获取到

    public enum ValidateCodeType {
        /**
         * 短信验证码
         */
        SMS {
            @Override
            public String getParamNameOnValidate() {
                return SecurityConstants.DEFAULT_PARAMETER_NAME_CODE_SMS;
            }
        },
        /**
         * 图片验证码
         */
        IMAGE {
            @Override
            public String getParamNameOnValidate() {
                return SecurityConstants.DEFAULT_PARAMETER_NAME_CODE_IMAGE;
            }
        };
    
        /**
         * 校验时从请求中获取的参数的名字
         * @return
         */
        public abstract String getParamNameOnValidate();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值