该包仅做验证码流程定义,未做实现(可以类比j2ee规范、jsr等,只做流程定义,不做实现)
- TODO
- 调用频率保护,如防止同一手机号频发调用短信验证码接口(优先级低,可以通过其他方式实现)
ValidateCodeSecurityConfig 将 ValidateCodeFilter 注册进 spring 容器
ValidateCodeFilter 作为安全过滤器上的一环,每个请求都会走它的 doFilterInternal() 方法来过滤
该方法会根据配置项判定是否要需要检查验证码,
如果未通过校验,则交给
- 根据配置确定是否需要校验验证码?
- 需要校验(如登录认证请求、支付请求等,该部分支持通过配置文件动态扩展)
- 根据配置的验证码类型(如图形验证码、短信验证码等,该部分支持扩展和配置)
- 从
ValidateCodeProcessorHolder#getProcessor中获取对应类型的验证码处理器ValidateCodeProcessor - 能否找到一个该验证方式对应的处理器?
- 找到
- 将请求交给对应的处理器(
ValidateCodeProcessor)处理- 校验通过,请求放行
- 校验不通过(可能是:验证码错误、验证码过期、验证码不存在等),抛出
ValidateCodeAuthenticationException
- 将请求交给对应的处理器(
- 未找到
- 抛出
NoSuchValidateCodeProcessorException异常,交给AuthenticationFailureHandler处理
- 抛出
- 找到
- 不需要校验(未在配置文件配置)
- 放行
- 需要校验(如登录认证请求、支付请求等,该部分支持通过配置文件动态扩展)
ValidateCodeProcessorHolder
维护所有的 ValidateCodeProcessor,便于通过 ValidateCodeType 获取对应的处理器,通过 Spring 的Bean注入实现了简单的 SPI 机制
ValidateCodeProcessor
验证码处理器,负责验证码的 生成(create)、校验(validate)
AbstractValidateCodeProcessor 是他的一个基本实现,进一步抽象了一般情况的验证码的生成和校验逻辑
- 生成(
create)逻辑- 通过
ValidateCodeGenerator生成,然后委托给ValidateCodeStore存储
- 通过
- 校验(
validate)逻辑- 获取请求中的验证码,从
ValidateCodeStore获取验证码,进行比对
- 获取请求中的验证码,从
ValidateCodeGenerator
验证码生成器,负责生成验证码DTO (ValidateCodeDTO),其继承了 ValidateCodeType 表示负责特定类型验证码的生成(单一职责)
ValidateCodeType
验证码类型,用于统一标记类的职责
ValidateCodeStore
验证码存储,负责保存验证码DTO (ValidateCodeDTO),如保存在 Session 中,为了同时支持实现单机和集群,故定义该接口。
ValidateCodeDTO
验证码DTO,保存验证码相关信息,以图形验证码为例:图片高、宽等
learn-security-starter-code 中提供了 图形验证码(ImageValidateCodeType)、短信验证码(SmsValidateCodeType) 完整流程的实现。
-
扩展:图片验证码默认内容为随机字母与数字,希望修改其图片形式(如改为类似
1 + 3 = ?的算式形式、或是改为拖动拼图等形式)。(有多种实现方式,下仅举例一种)- 参考
ImageCodeProcessor实现生成验证码的方法,并注入到 Spring 中 - 新建
MyImageCodeProcessor继承AbstractValidateCodeProcessor实现validate方法,并注入到 Spring 中
- 参考
-
扩展:新增一个新形式的验证码,如邮件验证码
- 可参照
starter中的进行扩展 - 新建邮件验证码类型
EmailValidateCodeType,以及对应的处理器EmailCodeProcessor - 新建
EmailCodeGenerator或在EmailCodeProcessor中重写create方法 - 将
EmailCodeProcessor注入到 Spring 容器中
- 可参照
ValidateCodeController 提供了用于获取验证码的默认接口,路径为 /code?type=xxx
- 扩展:修改获取验证码的 url
- 添加自己的
Controller,可以根据请求参数从ValidateCodeProcessorHolder中获取
- 添加自己的
提供了 ValidateCodeStore 两种实现
-
存储到
session中(默认) -
存储到
redis中 -
扩展:希望其他存储方式,如
Ehcache、Hazelcast等- 实现
ValidateCodeStore接口,实现save、get、remove方法即可
- 实现