Php 自定义密码编码器symfony 5
我正在尝试集成我的旧数据库密码验证器,为此我配置了自定义编码密码: 我使用的是symfony5.1和php7.4 这是我的安全Php 自定义密码编码器symfony 5,php,symfony,Php,Symfony,我正在尝试集成我的旧数据库密码验证器,为此我配置了自定义编码密码: 我使用的是symfony5.1和php7.4 这是我的安全 security: encoders: App\Entity\User: algorithm: auto #para oracle puse auto app_encoder: id: 'App\Security\Encoder\MyCustomPasswo
security:
encoders:
App\Entity\User:
algorithm: auto
#para oracle puse auto
app_encoder:
id: 'App\Security\Encoder\MyCustomPasswordEncoder'
#para oracle
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
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:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
lazy: true
provider: app_user_provider
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: app_logout
#target: app_logout
remember_me:
secret: '%kernel.secret%'
lifetime: 2592000 # 30 days in seconds
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
#- { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
这是我的密码自定义编码器src/Security/encoder/MyCustomPasswordEncoder.php
<?php
namespace App\Security\Encoder;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class MyCustomPasswordEncoder implements UserPasswordEncoderInterface
{
/**
* {@inheritdoc}
*/
public function encodePassword(UserInterface $user, string $plainPassword)
{
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->encodePassword($plainPassword, $user->getSalt());
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(UserInterface $user, string $raw)
{
if (null === $user->getPassword()) {
return false;
}
die('Esta usando la mia');
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt());
}
/**
* {@inheritdoc}
*/
public function needsRehash(UserInterface $user): bool
{
if (null === $user->getPassword()) {
return false;
}
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->needsRehash($user->getPassword());
}
}
事情可能会变得混乱,因为涉及到两个接口:PasswordEncoderface和UserPasswordEncoderface。有一种倾向是希望创建自定义UserPasswordEncoderInterface,因为您正在编码用户密码。但事实上,UserPasswordEncoder对象基本上只是底层PasswordEncoder的包装器
因此,您需要在PasswordEncoder对象中实现旧数据库密码验证器:
namespace App\Security;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
class MyPasswordEncoder implements PasswordEncoderInterface
{
public function encodePassword(string $raw, ?string $salt)
{
return 'ENCODED' . $raw;
}
public function isPasswordValid(string $encoded, string $raw, ?string $salt)
{
return true;
}
public function needsRehash(string $encoded): bool
{
return false;
}
}
接下来,您需要告诉Symfony为给定类型的用户使用自定义编码器:
# config/packages/security.yaml
security:
encoders:
App\Entity\User:
id: App\Security\MyPasswordEncoder
此时,您可以确认编码器正在与以下设备一起使用:
$ bin/console security:encode-password xxx
Encoder used App\Security\MyPasswordEncoder
Encoded password ENCODEDxxx
这应该足以让你行动起来。但冒着增加更多混淆的风险,这里有一个小测试命令,它试图显示UserPasswordEncoderInterface、PasswordEncoderInterface和EncoderFactoryInterface之间的关系,EncoderFactoryInterface基本上根据security.yaml映射为给定用户选择正确的编码器:
class UserCommand extends Command
{
protected static $defaultName = 'app:user';
private $encoderFactory;
private $userPasswordEncoder;
public function __construct(EncoderFactoryInterface $encoderFactory, UserPasswordEncoderInterface $userPasswordEncoder)
{
parent::__construct();
$this->encoderFactory = $encoderFactory;
$this->userPasswordEncoder = $userPasswordEncoder;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$encoder = $this->encoderFactory->getEncoder(User::class);
echo get_class($encoder) . "\n";
$user = new User();
$encoded = $this->userPasswordEncoder->encodePassword($user,'zzz');
echo $encoded . "\n";
return Command::SUCCESS;
}
}
还想指出问题中的链接指向使用命名编码器。命名编码器允许将多个编码器映射到单个实体类,然后允许实体根据某些属性选择编码器。例如,管理员用户可能使用与普通用户不同的编码器。命名编码器不适用于此用例
不过,您可能希望了解如何自动执行。配置后,用户可以使用旧编码器登录,然后自动更新为新编码器。您到底想实现什么?为所有用户使用您自己的编码器还是仅为其中的一部分?您提供的链接谈到了命名编码器,但我没有看到任何证据表明您正在这样做。您需要了解UserPasswordEncoderInterface和PasswordEncoderInterface之间的区别。您的自定义编码器将实现PasswordEncoderface。将编码器映射到安全文件中的用户。我可以给你一个完整的例子,但不清楚你到底想做什么。我需要为所有用户使用我自己的编码器。我不理解UserPasswordEncoderInterface和PasswordEncoderInterface之间的区别,我找不到文档。如果我可以使用自己的编码器,我将尝试添加对数据库函数的调用,以验证isValidPassword中的密码method@RaulCejas这一切都变得有点混乱。有些交互不适合stackoverflow。考虑在SeffReDeDIT上打开一个帖子,在这里只是引用这个问题。我也监视它。我在下面的回答确实表明,当一切都连接好时,注入UserPasswordEncoderInterface会按预期工作。“bin/console debug:container UserPasswordEncoderInterface”应该会生成默认的“Symfony\Component\Security\Core\Encoder\UserPasswordEncoder”类。我已经为此忙了3天了。感谢您为我们这些尝试使用遗留系统的人澄清这一点。
class UserCommand extends Command
{
protected static $defaultName = 'app:user';
private $encoderFactory;
private $userPasswordEncoder;
public function __construct(EncoderFactoryInterface $encoderFactory, UserPasswordEncoderInterface $userPasswordEncoder)
{
parent::__construct();
$this->encoderFactory = $encoderFactory;
$this->userPasswordEncoder = $userPasswordEncoder;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$encoder = $this->encoderFactory->getEncoder(User::class);
echo get_class($encoder) . "\n";
$user = new User();
$encoded = $this->userPasswordEncoder->encodePassword($user,'zzz');
echo $encoded . "\n";
return Command::SUCCESS;
}
}