最近实现了一个多端登录的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 Security 一键接入验证码登录和小程序登录的更多相关文章

  1. Spring Security 整合 微信小程序登录的思路探讨

    1. 前言 原本打算把Spring Security中OAuth 2.0的机制讲完后,用小程序登录来实战一下,发现小程序登录流程和Spring Security中OAuth 2.0登录的流程有点不一样 ...

  2. 【手摸手,带你搭建前后端分离商城系统】03 整合Spring Security token 实现方案,完成主业务登录

    [手摸手,带你搭建前后端分离商城系统]03 整合Spring Security token 实现方案,完成主业务登录 上节里面,我们已经将基本的前端 VUE + Element UI 整合到了一起.并 ...

  3. spring mvc+redis实现微信小程序登录

    本文将详细的介绍微信小程序的登录流程以及在ssm框架下如何实现小程序用户登录 登录流程概要 主要的登录流程可以参考官方提供的一张流程图: 1.微信前台页面: 在微信版本更新之后,提高了安全机制,我们需 ...

  4. 小程序登录、微信网页授权(Java版)

    首先呢,“登录”.“授权”.“授权登录”,是一样的意思,不用纠结. 写小程序授权登录的代码前,需要了解清楚openid与unionid的区别,这里再简单介绍一下: 腾讯有个 “微信·开放平台”,只有企 ...

  5. 基于Shiro,JWT实现微信小程序登录完整例子

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...

  6. 微信小程序登录JAVA后台

    代码地址如下:http://www.demodashi.com/demo/12736.html 登录流程时序登录流程时序 具体的登录说明查看 小程序官方API 项目的结构图: springboot项目 ...

  7. 做一个开源的小程序登录模块组件(token)

    先了解下SSO 对于单点登陆浅显一点的说就是两种,一种web端的基于Cookie.另一种是跨端的基于Token,一般想要做的都优先做Token吧,个人建议,因为后期扩展也方便哦. 小程序也是呢,做成t ...

  8. Flask与微信小程序登录(后端)

    开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步.这篇文章将介绍 python + flask + 微信小程序实现用户快速注册登录方案(本文主要进行后 ...

  9. Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(四):客户端强类型约束,自动生成 API TS 类型定义

    系列 云原生 API 网关,gRPC-Gateway V2 初探 Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇 Go + gRPC-Gateway(V2) ...

随机推荐

  1. laravel 公共类json库封装

    封装常用的接口响应: 创建 response.php 在app下创建如下文件下(目录及文件名可以自己设置) app/common/response.php,在内部补充如下代码: <?php /* ...

  2. tp5实现邮件发送(无注释)

    HTML代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  3. BSOJ5086题解

    题意略. 我们设 \([x^k]G_n(x)\) 代表深度为 \(n\) 的树,距离为 \(k\) 的点对数量,\([x^k]F_n(x)\) 为深度为 $ n $ 的树中,深度为 \(k\) 的节点 ...

  4. 写博客的技巧整理——基于Markdown

    我们需要掌握各种技巧,这样才能在写博客时游刃有余,以下内容觉得不错就点个赞吧 文章目录 1.目录与目录跳转 目录一(示例用勿点) 目录二(示例用勿点) 目录三(示例用勿点) 2.文字与图片 3.引用 ...

  5. Java数组(Array)和列表(ArryList)有什么区别?

    Array和ArryList的不同点 Array可以包含基本类型和对象类型,ArrayList只能包含对象类型 Array大小是固定的,ArrayList的大小动态变化的 ArrayList提供了更多 ...

  6. test 分支强制替换master 分支的办法

    test分支改动太多,并且master 分支好久没有改动.直接合并到master 分支的话,会产生很多冲突,几十个文件,修复冲突会花很多时间,并且是没有意义的.因此只能使用test 分支强制替换. 代 ...

  7. Net Framework 中托管代码与非托管代码的区别

    托管代码与非托管代码的区别 1 简单的说,就是代码被编译成MSIL后在.net的Framework下运行,同操作系统底层的交互都交给framework去做. 所谓非托管代码就是脱离了Framework ...

  8. NET程序的代码混淆、加壳与脱壳

    通常我们通过代码混淆.加密的形式达到软件保护的目的.在Web开发里我们接触过的可能就是JS代码加密了,可以通过对JS代码进行混淆.加密从而实现对核心JS代码的保护.如果没有接触过的可以在这里简单了解一 ...

  9. Java如何使用实时流式计算处理?

    我是3y,一年CRUD经验用十年的markdown程序员‍常年被誉为职业八股文选手 最近如果拉过austin项目代码的同学,可能就会发现多了一个austin-stream模块.其实并不会意外,因为这一 ...

  10. 七牛云简单实用-uploadManager.put(..)抛出异常

    描述: 本人小白,最近在写一个仿头条的项目,其中有用到七牛云做为图片的存储以代替本地服务其存储,按照视频教程配置服务器端的简单上传功能,总是报错: 参照官方文档:https://developer.q ...