【问题标题】:Symfony4 custom password encoderSymfony4 自定义密码编码器
【发布时间】:2018-07-17 13:54:23
【问题描述】:

我正在升级一个旧应用程序以使用 Symfony (v4) 作为后端,但我一直在尝试让身份验证正常工作。我的数据库存储用户的散列密码和盐,密码使用crypt php 函数。我也在使用 lexik JWT 包来尝试将令牌返回到前端。

除了来自 symfony/lexik 的“错误凭据”之外,我无法得到响应。

认为我的问题根源于 encoders 部分,我尝试实现自定义密码编码器,因为 crypt 使用根据 php 文档修改的 DES 算法,并且简单在我的 security.yaml 中使用以下内容不起作用。

encoders:
App\Entity\DB_1\User:
    algorithm: DES

这是我完整的 security.yaml

security.yaml

security:
encoders:
    App\Entity\DB_1\User:
        id: 'App\Security\MyPasswordEncoder'

providers:
    entity_provider:
        entity:
            class: App\Entity\MetallicBonds\User
            property: username

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    login:
        pattern:  ^/login
        stateless: true
        anonymous: true
        json_login:
            check_path: /login_check
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure

    register:
        pattern:  ^/register
        stateless: true
        anonymous: true

    api:
        pattern:  ^/test
        stateless: true
        anonymous: false
        provider: entity_provider
        guard:
            authenticators:
                - lexik_jwt_authentication.jwt_token_authenticator

access_control:
    - { path: ^/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/test, roles: IS_AUTHENTICATED_FULLY }

和我的自定义密码编码器MyPasswordEncoder.php

namespace App\Security;

use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class MyPasswordEncoder extends BasePasswordEncoder implements  
PasswordEncoderInterface
{
private $ignorePasswordCase;

public function __construct($ignorePasswordCase = false)
{
    $this->ignorePasswordCase = $ignorePasswordCase;
}

public function encodePassword($raw, $salt)
{
    // TODO: Implement encodePassword() method.
    return crypt($raw,$salt);
}

public function isPasswordValid($encoded, $raw, $salt)
{
    // TODO: Implement isPasswordValid() method.
    if ($this->isPasswordTooLong($raw)) {
        return false;
    }

    try {
        $pass2 = $this->encodePassword($raw, $salt);
    } catch (BadCredentialsException $e) {
        return false;
    }

    if (!$this->ignorePasswordCase) {
        return $this->comparePasswords($encoded, $pass2);
    }

    return $this->comparePasswords(strtolower($encoded), strtolower($pass2));
}
}

我想使用当前存储的密码,至少目前是这样,这样从旧系统到新系统的更改对于最终用户来说将是顺利的。有没有人成功使用 Symfony 4 的自定义密码编码器?

我应该注意,当我在 MyPasswordEncoder.php 中放置 xdebug 断点时,它永远不会停止应用程序,是否需要在其他地方注册该类以供 Symfony 使用?

【问题讨论】:

  • 纯属猜测,但我认为您的登录防火墙需要提供程序条目。
  • security.yaml 文件的缩进是否如 StackOverflow 上所见? encodersprovidersfirewalls 键应该是 security 键的子级,这里似乎不是这样。
  • 缩进是正确的,只是这里没有正确复制粘贴到文本框中

标签: php symfony authentication symfony4 lexikjwtauthbundle


【解决方案1】:

这是我的 security.yaml security: encoders: App\Entity\User: id: 'App\Security\Encoder\MyCustomPasswordEncoder'

这是我的代码

namespace App\Security\Encoder;


use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;

class MyCustomPasswordEncoder extends BasePasswordEncoder
{

private $algorithm;
private $encodeHashAsBase64;
private $iterations;

/**
 * @param string $algorithm          The digest algorithm to use
 * @param bool   $encodeHashAsBase64 Whether to base64 encode the password hash
 * @param int    $iterations         The number of iterations to use to stretch the password hash
 */
public function __construct(string $algorithm = 'sha1', bool $encodeHashAsBase64 = false, int $iterations = 0)
{
    $this->algorithm = $algorithm;
    $this->encodeHashAsBase64 = $encodeHashAsBase64;
    $this->iterations = $iterations;
}

/**
 * {@inheritdoc}
 */
public function encodePassword($raw, $salt)
{
    if ($this->isPasswordTooLong($raw)) {
        throw new BadCredentialsException('Invalid password.');
    }

    if (!in_array($this->algorithm, hash_algos(), true)) {
        throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
    }

    //$salted = $this->mergePasswordAndSalt($raw, $salt);
    $salted = $salt.$raw;
    $digest = hash($this->algorithm, $salted, true);

    // "stretch" hash
    for ($i = 1; $i < $this->iterations; ++$i) {
        $digest = hash($this->algorithm, $digest.$salted, true);
    }

    return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
}

/**
 * {@inheritdoc}
 */
public function isPasswordValid($encoded, $raw, $salt)
{
    return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
}

}

代码正确运行。旧代码是 symfony 1.4。

【讨论】:

  • 我做了类似的事情,我的自定义类的 ctor 被调用但不是“isPasswordValid”函数。你知道为什么吗?我正在尝试使用 JWT 包登录。
猜你喜欢
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2014-05-13
  • 2020-01-25
  • 1970-01-01
相关资源
最近更新 更多