You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LexikJWT与Scheb 2FA集成问题:验证码确认失败

问题:Symfony集成LexikJWT与Scheb2FA时验证码验证失败

环境配置

Security配置

firewalls:
  login:
    pattern: ^/login
    stateless: true
    provider: fos_userbundle
    json_login:
      check_path: /login_check
      username_path: _username
      password_path: _password
      success_handler: App\Application\Module\User\EventHandler\Security\AuthenticationSuccessHandler
      failure_handler: App\Application\Module\User\EventHandler\Security\AuthenticationFailureHandler
    user_checker: App\Application\Module\User\EventListener\Security\UserChecker
    two_factor:
      prepare_on_login: true
  main:
    pattern: ^/
    provider: fos_userbundle
    stateless: true
    guard:
      authenticators:
        - lexik_jwt_authentication.jwt_token_authenticator
    two_factor:
      check_path: 2fa_login_check
      auth_code_parameter_name: _auth_code
      authentication_required_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationRequiredHandler
      failure_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationFailureHandler
      success_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationSuccessHandler

Scheb2FA配置

# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/6.x/configuration.html
scheb_two_factor:
    security_tokens:
        - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
    email:
        enabled: true
        digits: 6
        mailer: App\Application\Module\User\Service\Auth\AuthCodeMailer

LexikJWT配置

lexik_jwt_authentication:
    private_key_path: '%jwt_private_key_path%'
    public_key_path:  '%jwt_public_key_path%'
    pass_phrase:      '%jwt_key_pass_phrase%'
    token_ttl:        '%jwt_token_ttl%'
    token_extractors:
        cookie:
            enabled: true
            name: shbee

问题现象

  • 提交验证码验证时,报错:User is not in a two-factor authentication process.
  • 排查发现当前认证使用的token为Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken,而非Scheb2FA要求的Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface

解决方案

1. 更新Scheb2FA的security_tokens配置

将JWTUserToken加入到Scheb2FA识别的token列表中,让Bundle能处理JWT类型的认证token:

scheb_two_factor:
    security_tokens:
        - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
        - Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken
    # ...其他原有配置

2. 调整Stateless模式下的2FA状态存储

由于项目使用stateless防火墙,默认session存储无法保存2FA中间状态,需实现自定义token存储:

  • 创建实现Scheb\TwoFactorBundle\Security\TwoFactor\Token\TwoFactorTokenStorageInterface的存储类(如基于Redis)
  • 在配置中指定该存储:
scheb_two_factor:
    # ...其他配置
    persistence:
        token_storage: App\Security\TwoFactor\CustomTwoFactorTokenStorage

3. 重构认证流程逻辑

  • 用户名密码验证阶段:在AuthenticationSuccessHandler中,不直接返回JWT,而是触发2FA准备流程,生成TwoFactorToken存入自定义存储,返回需验证2FA的响应。
  • 2FA验证阶段:在TwoFactorAuthenticationSuccessHandler中,验证通过后生成有效JWT并返回给客户端,完成全流程认证。

4. 修正防火墙的2FA配置顺序

确保main防火墙中two_factor配置在guard认证器之前,让2FA验证逻辑优先处理:

main:
    pattern: ^/
    provider: fos_userbundle
    stateless: true
    two_factor:
      check_path: 2fa_login_check
      auth_code_parameter_name: _auth_code
      authentication_required_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationRequiredHandler
      failure_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationFailureHandler
      success_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationSuccessHandler
    guard:
      authenticators:
        - lexik_jwt_authentication.jwt_token_authenticator

内容的提问来源于stack exchange,提问作者Tebby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 04:35:29