• Spring Security 一键接入验证码登录和小程序登录


    最近实现了一个多端登录的Spring Security组件,用起来非常丝滑,开箱即用,可插拔,而且灵活性非常强。我觉得能满足大部分场景的需要。目前完成了手机号验证码和微信小程序两种自定义登录,加上默认的Form登录,一共三种,现在开源分享给大家,接下来简单介绍一下这个插件包。

    DSL配置风格

    切入正题,先来看看配置:

        @Bean
        SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .mvcMatchers("/foo/**")
                    .access("hasAuthority('ROLE_USER')").anyRequest().authenticated()
                    .and()
                    // 默认form表单登录
                    .formLogin()
                    .and()
                    .apply(new LoginFilterSecurityConfigurer<>())
                    // 验证码登录
                    .captchaLogin(captchaLoginConfigurer ->
                                    // 验证码校验 1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                    captchaLoginConfigurer.captchaService(this::verifyCaptchaMock)
                                            // 根据手机号查询用户UserDetials  1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                            .captchaUserDetailsService(this::loadUserByPhoneMock)
                                            // 生成JWT 返回  1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                            .jwtTokenGenerator(this::tokenResponseMock)
                            //todo 其它配置省略……
                    )
                    // 小程序登录 同时支持多个小程序
                    .miniAppLogin(miniAppLoginConfigurer -> miniAppLoginConfigurer
                                    // 实现小程序多租户
                                    // 根据请求携带的clientid 查询小程序的appid和secret 1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                    .miniAppClientService(this::miniAppClientMock)
                                    // 小程序用户 自动注册和检索  1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                    .miniAppUserDetailsService(new MiniAppUserDetailsServiceMock())
                                    // 小程序sessionkey缓存 过期时间应该小于微信官方文档的声明   1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                    .miniAppSessionKeyCache(new MiniAppSessionKeyCacheMock())
                                    // 生成JWT 返回  1 在此处配置 优先级最高 2 注册为Spring Bean 可以免配置
                                    .jwtTokenGenerator(this::tokenResponseMock)
                            //todo 其它配置省略……
                    );
    
            return http.build();
        }
    

    这种风格完全贴合了Spring SecurityDSL配置风格,不仅仅高大上,而且可以按需配置。如果你没有验证码登录直接删掉captchaLogin方法;如果你没有微信小程序登录直接删掉miniAppLogin方法。甚至还可以对单种登录进行细粒度定制化,formLogin有的功能基本验证码登录和微信小程序登录的都有。

    为什么这么灵活?

    这里抽象了一个登录配置类:

     public abstract class AbstractLoginFilterConfigurer<H extends HttpSecurityBuilder<H>, 
             C extends AbstractLoginFilterConfigurer<H, C, F>, 
             F extends AbstractAuthenticationProcessingFilter>
             extends AbstractHttpConfigurer<AbstractLoginFilterConfigurer<H, C, F>, H> {
                 // 省略……
             }
    

    所有额外的登录渠道大都可以通过这个类来扩展,负责验证码登录的CaptchaLoginFilterConfigurer和微信小程序登录的MiniAppLoginFilterConfigurer都是该类实现的,基本上你看了源码也能照葫芦画瓢来一个。

    另外上面这些配置项接口,都可以放在Spring IoC中,配置类能自动获取,不过优先级最高的还是通过上面代码中配置的具体实现,原理参见下面的的样例:

      @Override
         protected AuthenticationSuccessHandler defaultSuccessHandler(H http) {
             // 如果配置类没有配置 就尝试去Spring IoC中发现
             if (this.jwtTokenGenerator == null) {
                 ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
                 jwtTokenGenerator = getBeanOrNull(applicationContext, JwtTokenGenerator.class);
             }
             Assert.notNull(jwtTokenGenerator, "jwtTokenGenerator is required");
             return new LoginAuthenticationSuccessHandler(jwtTokenGenerator);
         }
     ​
     ​
         public final <T> T getBeanOrNull(ApplicationContext applicationContext, Class<T> beanType) {
             String[] beanNames = applicationContext.getBeanNamesForType(beanType);
             if (beanNames.length == 1) {
                 return applicationContext.getBean(beanNames[0], beanType);
             }
             return null;
         }
    

    使用方法

    自行使用Maven命令mvn install到本地仓库,然后引入:

            <dependency>
                <groupId>cn.felord</groupId>
                <artifactId>spring-security-extension</artifactId>
                <version>1.0.0</version>
            </dependency>
    

    然后参考样例sample项目进行开发,登录方式有三种。

    普通登录

    原生Spring Security接口

    
    POST /login?username=user&password=12345 HTTP/1.1
    Host: localhost:8080
    

    验证码登录

    需要先实现必须的配置接口

    发送验证码后调用验证码登录接口:

    
    POST /login/captcha?phone=11111111111&captcha=123123 HTTP/1.1
    Host: localhost:8080
    

    小程序登录

    需要先实现必须的配置接口

    前端先调用微信授权登录接口获取openid:

    
    POST /miniapp/preauth?clientId=wxxda23234&jsCode=051A23234ZHa1tZ5yj3AOlFr HTTP/1.1
    Host: localhost:8080
    

    响应:

    {
        "code": 200,
        "data": {
            "errcode": null,
            "errmsg": null,
            "sessionKey": null,
            "openid": "oWmZj5QBrZxxxxx8OUxRrZJi4",
            "unionid": "oS-dxxxxxx4w_x7dA-h9MIuA"
        },
        "msg": "",
        "identifier": true
    }
    

    然后调用小程序登录接口:

    POST /login/miniapp HTTP/1.1
    Host: localhost:8080
    Content-Type: application/json
    
    {
        "clientId": "wxd14qr6",
        "openId": "oWmZj5QBrZIBks0xx8OUxRrZJi4",
        "unionId": "oS-dK520tgW8xxxx7dA-h9MIuA",
        "iv":"LQUOt8BSTa7xxxpe1Q==",
        "encryptedData": "10hn3o4xxxxxrO/Ag5nRD3QkLSzduKnWuzN9B/H4Y0G5mDPR8siA7T8yaaqZsrMycLAoe2qrd1J75yYetYuWifiq3jUrcceRZHVxxl9LnQdW8f5+pMTnQtCYiMJ7Jm9paCw2Bh+5Lowkyqkx1q0fALvCQ9LXPPLAbLOB9CavRfKoenAmyyHQjZ/6lz0njzA=="
    }
    
    

    获取方式

    Gitee: felord/spring-security-login-extension

    关注公众号:Felordcn 获取更多资讯

    个人博客:https://felord.cn

  • 相关阅读:
    上线Spring boot-若依项目
    Linux:补充一些常用命令
    axios.js get 请求 生成参数的方法,兼容golang gin
    著名的勃艮第葡萄酒是如何分类的?
    【面试题】前端面试真题 年前端面试
    简单的CNN实现——MNIST手写数字识别
    步力宝科技爆款产品定位,开创智能物联网新商业
    SpringBoot+Vue项目医疗管理系统
    静态链表(及其两个例题)
    Map合并、根据value排序(热词)
  • 原文地址:https://www.cnblogs.com/felordcn/p/16095503.html