在Web应用的安全领域,双因素认证(2FA)已经是保护用户账户的标配方案了。TOTP(基于时间的一次性密码算法)是这个领域的主流技术,而Google Authenticator则是其最具代表性的客户端。今天咱们聊的,是一个Spring Boot的集成方案——tutorials4j-framework-web-google-auth。它做的事情很纯粹:把TOTP服务的自动配置、请求拦截、管理接口这些能力都封装好,让你拿到手就能用。
![[044][Web模块]基于 Google Authenticator 的 TOTP 双因素认证框架设计与实现](/uploadfile/2026/0707/50e23ef31ec6d2adf509a2b926c99ebe.webp)
一、整体架构与功能概览
框架底层依赖的是 com.warrenstrange.googleauth 这个库,专门为Spring Boot 3.x量身打造。它具备以下几个核心能力:
- 自动配置:能根据环境条件自动创建
GoogleAuthenticator实例,并把需要的依赖都给你注入好。 - TOTP业务服务:把密钥生成、验证码校验、二维码URL生成这些操作都封装成了现成的服务接口。
- 请求过滤器:提供一个统一的拦截器,专门保护那些需要2FA的请求。它会从请求头里读取用户名和验证码,然后自动完成校验。
- 管理接口:提供了REST API,方便你生成绑定二维码,或者测试校验逻辑。
- 凭证仓库扩展:你可以从YAML配置文件读取用户密钥,也可以换成更灵活的数据源,比如数据库。
- 配置定制:像时间步长、窗口大小这些TOTP算法的核心参数,都留了口子让你调整。
它在整个Spring Boot应用里的位置大致是这样的:
用户请求 → [GoogleAuthRequestFilter] → 校验 TOTP → 业务处理↓ 失败抛出异常
二、核心组件分析
1. 自动配置类 GoogleAuthWebConfiguration
这个类的作用很明确:一旦它在类路径里发现 GoogleAuthenticator,就会自动启动,并装配以下几个核心Bean:
| Bean | 作用 |
|---|---|
GoogleAuthenticator | TOTP算法的核心实现,绑定着你自定义的凭证仓库。 |
XICredentialRepository | 默认用的是YAML配置仓库,当然,你可以覆盖它。 |
GoogleAuthService | 这就是服务门面,对上提供业务接口。 |
FilterRegistrationBean | 负责注册过滤器,你可以自定义匹配的路径和优先级。 |
关键的装配逻辑大概像这样:
@Bean
GoogleAuthenticator googleAuthenticator(XICredentialRepository repository,
ObjectProvider
2. 凭证仓库接口 XICredentialRepository
这个接口继承自 ICredentialRepository,它的特别之处在于增加了一个密码校验方法。这其实是一个很巧妙的设计,为“密码+TOTP”这种两步验证提供了很好的扩展点。
public interface XICredentialRepository extends ICredentialRepository {
boolean verifyPassword(String userName, String password);
}
框架内置了一个基于YAML的内存实现 YamlCredentialRepository,如果你只是小规模固定用户做测试,它完全够用。要是上了生产环境,自己动手实现一个数据库版本就行了。
3. TOTP 业务服务 GoogleAuthService
这个服务对底层库的调用进行了封装,目的是让你用起来更顺手。它主要提供了这几个方法:
generateSecretKey():生成一个随机的密钥。verifyByUserName()/verifyBySecretKey():用来校验验证码。getQRBarcodeURL():生成otpauth://协议格式的URL,是二维码生成的原材料。
4. 请求过滤器 GoogleAuthRequestFilter
它继承自 OncePerRequestFilter,会从请求头里拿两样东西:
X-Google-Auth-Username(实在没有的话,它会尝试从SecurityUtils.getAccount()获取)X-Google-Auth-Code
校验一旦失败,就会抛出 WebFrameworkException,交给全局异常处理器去处理。这里有个值得注意的安全细节:校验通过后,过滤器会通过 RemoveHeaderRequestWrapper 把验证码从请求头里移除,避免下游业务代码无意中读到这些敏感信息。
5. 管理接口 GoogleAuthController
这个控制器对外开放了两个端点:
| 端点 | 方法 | 功能 |
|---|---|---|
/t4j/google-auth/check | POST | 手动校验用户名和验证码 |
/t4j/google-auth/generate/qr | GET | 为用户生成新密钥,并直接返回一张二维码图片(PNG格式) |
三、配置说明
具体怎么配?在 application.yml 里加上这么一段就行了:
tutorials4j:
web:
google-auth:
otp-auth-totp-url: "myapp" # 二维码中显示的应用名称
credentials:
# 静态用户列表(仅用于 YAML 仓库)
- username: admin
password: admin123
security-key: # 可选,若空则首次生成后自动填充内存
- username: user1
password: pass123
filter: # 过滤器配置
url-patterns:
- "/api/secure/*"
order: 1
name: "googleAuthFilter"
这里有几个关键点需要说明:
otp-auth-totp-url:它影响二维码URI中的issuer参数。客户端扫描后,显示的名称会是“myapp (username)”这种格式。credentials:这个配置只在用默认的YamlCredentialRepository时才生效。注意,security-key字段如果为空,第一次调用generateSecretKey时会动态生成并保存在内存里,但不会写回配置文件。所以生产环境,强烈建议用数据库来管理凭证。filter:通过ServletFilterOptions来配置需要拦截的路径、过滤器的执行顺序和名称。
四、使用流程
整个使用流程很清晰,分为两步:
1. 用户首次绑定
- 前端调用
GET /t4j/google-auth/generate/qr?username=admin。 - 后端生成一个全新的密钥,并直接返回二维码图片。
- 用户打开Google Authenticator之类的App扫描二维码,绑定就完成了。
2. 登录/受保护接口调用
在后续的请求里,客户端需要在Header里带上这两样东西:
X-Google-Auth-Username: admin
X-Google-Auth-Code: 123456
过滤器会自动校验,通过了就放行。要是校验失败,就会抛出异常,前端捕获到后就可以给出相应的提示。
五、扩展与定制
框架的扩展性很不错,下面举几个常见例子:
1. 调整 TOTP 算法参数
实现一个 GoogleAuthenticatorConfigCustomizer Bean 即可:
@Component
public class MyConfigCustomizer implements GoogleAuthenticatorConfigCustomizer {
@Override
public void customize(GoogleAuthenticatorConfig config) {
config.setTimeStepSizeInMillis(30000); // 30秒步长
config.setWindowSize(2); // 允许前后一个时间窗口
}
}
2. 自定义凭证仓库(例如数据库)
实现 XICredentialRepository,并声明为 @Primary 或 @Component。框架会自动优先使用你提供的实现,而不会去碰那个基于YAML的版本。
@Component
public class DatabaseCredentialRepository implements XICredentialRepository {
// 实现 getSecretKey, sa veUserCredentials, verifyPassword
}
3. 动态获取当前用户名
默认过滤器会优先从请求头拿用户名,如果拿不到,就会调用 SecurityUtils.getAccount()。你可以根据自己的认证上下文(比如用了Spring Security)来修改这个工具类的实现。
六、总结
总的来说,这个框架通过Spring Boot的自动配置机制,把Google Authenticator无缝地集成到了Web应用里。它的优点非常突出:
- 开箱即用:默认的YAML配置就能驱动起来,非常适合快速原型验证或小规模内网应用。
- 安全设计:过滤器在校验后会主动“擦除”验证码请求头,避免泄露;同时还为“密码+TOTP”这种双重校验提供了扩展接口。
- 灵活扩展:算法参数可以定制,凭证仓库支持热插拔,能适应不同的部署环境。
- 开发友好:内置的管理接口,无论是测试还是帮用户绑定,都非常方便。
在实际的生产环境中,还是建议把凭证仓库换成数据库实现,并配合Spring Security这类权限框架,让TOTP验证作为第二道防线,这样整体的安全水平会更高。
