Spring Security 实战干货:从零手写一个验证码登录

合集

https://mp.weixin.qq.com/s/4jgENU5zbGEtlf2wdbKp1A

1. 前言

前面关于Spring Security胖哥又写了两篇文章,分别图文并茂地介绍了UsernamePasswordAuthenticationFilterAuthenticationManager。很多同学表示无法理解这两个东西有什么用,能解决哪些实际问题?所以今天就对这两篇理论进行实战运用,我们从零写一个短信验证码登录并适配到Spring Security体系中。如果你在阅读中有什么疑问可以回头看看这两篇文章,能解决很多疑惑。

当然你可以修改成邮箱或者其它通讯设备的验证码登录。

2. 验证码生命周期

验证码存在有效期,一般 5 分钟。一般逻辑是用户输入手机号后去获取验证码,服务端对验证码进行缓存。在最大有效期内用户只能使用验证码验证成功一次(避免验证码浪费);超过最大时间后失效。

验证码的缓存生命周期:

public interface CaptchaCacheStorage {

    /**
     * 验证码放入缓存.
     *
     * @param phone the phone
     * @return the string
     */
    String put(String phone);

    /**
     * 从缓存取验证码.
     *
     * @param phone the phone
     * @return the string
     */
    String get(String phone);

    /**
     * 验证码手动过期.
     *
     * @param phone the phone
     */
    void expire(String phone);
}

我们一般会借助于缓存中间件,比如RedisEhcacheMemcached等等来做这个事情。为了方便收看该教程的同学们所使用的不同的中间件。这里我结合Spring Cache特意抽象了验证码的缓存处理。

务必保证缓存的可靠性,这与用户的体验息息相关。

接着我们就来编写和业务无关的验证码服务了,验证码服务的核心功能有两个:发送验证码验证码校验。其它的诸如统计、黑名单、历史记录可根据实际业务定制。这里只实现核心功能。

接下来就可以根据CaptchaService编写短信发送接口/captcha/{phone}了。

3. 集成到 Spring Security

下面的教程就必须用到前两篇介绍的知识了。我们要实现验证码登录就必须定义一个Servlet Filter进行处理。它的作用这里再重复一下:

  • 拦截短信登录接口。

  • 获取登录参数并封装为Authentication凭据。

  • 交给AuthenticationManager认证。

我们需要先定制AuthenticationAuthenticationManager

3.1 验证码凭据

Authentication在我看来就是一个载体,在未得到认证之前它用来携带登录的关键参数,比如用户名和密码、验证码;在认证成功后它携带用户的信息和角色集。所以模仿UsernamePasswordAuthenticationToken 来实现一个CaptchaAuthenticationToken,去掉不必要的功能,抄就完事儿了:

3.2 验证码认证管理器

我们还需要定制一个AuthenticationManager来对上面定义的凭据CaptchaAuthenticationToken进行认证处理。下面这张图有必要再拿出来看一下:

imgProviderManager

定义AuthenticationManager只需要定义其实现ProviderManager。而ProviderManager又需要依赖AuthenticationProvider

所以我们要实现一个专门处理CaptchaAuthenticationTokenAuthenticationProviderAuthenticationProvider的流程是:

  1. CaptchaAuthenticationToken拿到手机号、验证码。

  2. 利用手机号从数据库查询用户信息,并判断用户是否是有效用户,实际上就是实现UserDetailsService接口

  3. 验证码校验。

  4. 校验成功则封装授信的凭据。

  5. 校验失败抛出认证异常。

根据这个流程实现如下:

然后就可以组装ProviderManager了:

经过3.13.2的准备,我们的准备工作就完成了。

3.3 验证码认证过滤器

定制好验证码凭据和验证码认证管理器后我们就可以定义验证码认证过滤器了。修改一下UsernamePasswordAuthenticationFilter就能满足需求:

这里我们指定了拦截验证码登陆的请求为:

接下来就是配置了。

3.4 配置

我把所有的验证码认证的相关配置集中了起来,并加上了注释。

然而这并没有完,你需要将CaptchaAuthenticationFilter配置到整个Spring Security的过滤器链中,这种看了胖哥教程的同学应该非常熟悉了。

配置验证码认证过滤器到WebSecurityConfigurerAdapter中

img

请特别注意:务必保证登录接口和验证码接口可以匿名访问,如果是动态权限可以给接口添加 ROLE_ANONYMOUS 角色。

大功告成,测试如下:

模拟验证码登录

img

而且原先的登录方式不受影响,它们可以并存。

4. 总结

通过对UsernamePasswordAuthenticationFilterAuthenticationManager的系统学习,我们了解了Spring Security认证的整个流程,本文是对这两篇的一个实际运用。相信看到这一篇后你就不会对前几篇的图解懵逼了,这也是理论到实践的一次尝试。DEMO 可以通过公众号:码农小胖哥 回复captcha 获取,如果有用还请关注、点赞、转发给胖哥一个创作的动力。

Last updated

Was this helpful?