使用不同于密码的字段对 HTTP Basic 进行身份验证

Authentication for HTTP Basic with a field different from password

在 Symfony 5 项目中,我有一个 User 实体,其中包含两个字段“password”(散列)和“smsCode"(普通)。

创建账户时,首先使用smsCode进行认证,直到用户后来设置密码(然后我们使用不为空的密码,忽略smsCode)。

我想要实现的目标:通过 HTTP Basic 进行身份验证,但使用 smsCode 而不是散列密码。

我通过编辑我的 LoginFormAuthenticator 上的 checkCredentials() 功能,设法使用表单登录来完成这项工作:我可以使用我的短信代码而不是我的密码通过表单登录。

但是当我尝试通过 HTTP Basic 进行身份验证时,会调用 DaoAuthenticationProvider.php 上的 checkAuthentication() 函数,并且此 class 使用 $user->getPassword() 获取密码。有什么方法可以覆盖/扩展此 checkAuthentication() 函数,以便我可以首先检查普通 smsCode ($user->getSmsCode()) 而不是散列密码?

#security:
encoders:
    App\Entity\User:
        algorithm: auto

providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        entity:
            class: App\Entity\User
            property: email
firewalls:
    dev:
        # profiler (dev only)
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        anonymous: true
        lazy: true
        provider: app_user_provider
        http_basic: true
        guard:
            authenticators:
                - App\Security\LoginFormAuthenticator
        logout:
            path: app_logout

我尝试编辑我的 getPassword() 函数以首先检查短信代码:

public function getPassword(): string
{
    if (!empty($this->smsCode)) {
        return (string) $this->smsCode;
    } else {
        return (string) $this->password;
    }
}

不幸的是,由于密码是散列的,它一直在验证失败,因为它正在寻找 smsCode 的散列版本(DaoAuthenticationProvider.php 中的函数 isPasswordValid()

(顺便说一下,当提供密码而不是短信代码时,身份验证工作完美)

为了保持逻辑(和代码)流程相同,您目前已经将哈希密码作为目标变量,因此当您生成 SMS 代码时,您可以将 SMS 代码的哈希版本添加到用作替代散列密码值的数据库。

然后在使用 HTTPAuth 时,您可以简单地引用此“hashedSMS”字符串而不是哈希密码字符串,以进行比较。


注意:为了安全; SMScode 应该有足够的熵,所以应该足够长 - 通常超过 8 个字符。

通常在当前的生态系统中,SMS 代码比密码更短且更简单,并且由于它们的传输方法(通过移动 phone 短信)极其不安全并且容易被窃听和拦截,这使得代码作为应用程序安全中的弱点。

这种身份验证方法只能作为最后的手段。

  • Also as a final side note; lots of websites use SMS codes as a "two-factor-authentication" method, despite this not being 2FA and despite this form of authentication being easily open to abuse and compromise.

    In fact most big web businesses with ask your mobile number simply as a thin veneer of "security" and really just to collect a phone number to connect with your account for their own tracking and marketting purposes, whilst claiming it's some form of "better security".