Symfony provides PasswordHasher component for hashing and verifying passwords. This component supports various built-in password hashers. There can be a case when password hasher is not implemented for the required hashing algorithm.
This tutorial provides example how to create custom password hasher in Symfony 7 application.
PasswordHasher component can be installed using the following command:
composer require symfony/password-hasher
The password hashing class should implement PasswordHasherInterface
. It requires defining the hash
, verify
and needsRehash
methods. In the hash
and verify
methods recommended checking the password length. It should be no longer than 4096 characters. For this purpose the isPasswordTooLong
method can be used provided in the CheckPasswordLengthTrait
.
<?php
namespace App\Security\Hasher;
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\PasswordHasher\Hasher\CheckPasswordLengthTrait;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
class CustomPasswordHasher implements PasswordHasherInterface
{
use CheckPasswordLengthTrait;
public function hash(string $plainPassword): string
{
if ($this->isPasswordTooLong($plainPassword)) {
throw new InvalidPasswordException();
}
return md5($plainPassword);
}
public function verify(string $hashedPassword, string $plainPassword): bool
{
if ('' === $plainPassword || $this->isPasswordTooLong($plainPassword)) {
return false;
}
return md5($plainPassword) === $hashedPassword;
}
public function needsRehash(string $hashedPassword): bool
{
return false;
}
}
For testing purpose, create a User
class that implements PasswordAuthenticatedUserInterface
and has password
property:
<?php
namespace App\Entity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
class User implements PasswordAuthenticatedUserInterface
{
private string $password;
public function getPassword(): string { return $this->password;}
public function setPassword(string $password): void { $this->password = $password; }
}
Framework use
In the security.yaml
file, we can define custom password hasher using id
option as follows:
security:
# ...
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
id: 'App\Security\Hasher\CustomPasswordHasher'
For testing purpose, we can use the following controller:
<?php
namespace App\Controller;
use App\Entity\User;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
class TestController
{
#[Route('/')]
public function index(UserPasswordHasherInterface $passwordHasher): Response
{
$user = new User();
$plaintextPassword = 'pwd123';
$hashedPassword = $passwordHasher->hashPassword($user, $plaintextPassword);
$user->setPassword($hashedPassword);
if (!$passwordHasher->isPasswordValid($user, $plaintextPassword)) {
return new Response('Invalid password');
}
return new Response('Valid password. Hash: '.$hashedPassword);
}
}
Standalone use
PasswordHasher component can be used in any PHP application independently of the Symfony framework. We can create an instance of password hasher using the PasswordHasherFactory
class.
<?php
use App\Entity\User;
use App\Security\Hasher\CustomPasswordHasher;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
require_once __DIR__.'/vendor/autoload.php';
$passwordHasherFactory = new PasswordHasherFactory([
PasswordAuthenticatedUserInterface::class => [
'class' => CustomPasswordHasher::class,
'arguments' => [],
],
]);
$passwordHasher = new UserPasswordHasher($passwordHasherFactory);
$user = new User();
$plaintextPassword = 'pwd123';
$hashedPassword = $passwordHasher->hashPassword($user, $plaintextPassword);
$user->setPassword($hashedPassword);
if (!$passwordHasher->isPasswordValid($user, $plaintextPassword)) {
echo 'Invalid password';
die;
}
echo 'Valid password. Hash: '.$hashedPassword;
The 3 Comments Found
Hi,
how can i use CustomPasswordHasher standalone?
Hi
I updated the tutorial how to use custom password hasher standalone.
Thank, man!
That's also works for SF5!
Leave a Comment
Cancel reply