[START CHUNK 2/3]
### test2.txt ###

UserPasswordHasherInterface
{
 // ...

 public function needsRehash(string $hashed): bool
 {
 // check whether the current password is hashed using an outdated hasher
 $hashIsOutdated = ...;

 return $hashIsOutdated;
 }
}
Dynamic Password Hashers
Usually, the same password hasher is used for all users by configuring it to apply to all instances of a specific class. Another option is to use a "named" hasher and then select which hasher you want to use dynamically.

By default (as shown at the start of the article), the auto algorithm is used for App\Entity\User.

This may be secure enough for a regular user, but what if you want your admins to have a stronger algorithm, for example auto with a higher cost. This can be done with named hashers:

 Copy
# config/packages/security.yaml
security:
 # ...
 password\_hashers:
 harsh:
 algorithm: auto
 cost: 15
This creates a hasher named harsh. In order for a User instance to use it, the class must implement PasswordHasherAwareInterface. The interface requires one method - getPasswordHasherName() - which should return the name of the hasher to use:

 Copy
// src/Entity/User.php
namespace App\Entity;

use Symfony\Component\PasswordHasher\Hasher\PasswordHasherAwareInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class User implements
 UserInterface,
 PasswordAuthenticatedUserInterface,
 PasswordHasherAwareInterface
{
 // ...

 public function getPasswordHasherName(): ?string
 {
 if ($this->isAdmin()) {
 return 'harsh';
 }

 return null; // use the default hasher
 }
}
When migrating passwords, you don't need to implement PasswordHasherAwareInterface to return the legacy hasher name: Symfony will detect it from your migrate\_from configuration.

If you created your own password hasher implementing the PasswordHasherInterface, you must register a service for it in order to use it as a named hasher:

 Copy
# config/packages/security.yaml
security:
 # ...
 password\_hashers:
 app\_hasher:
 id: 'App\Security\Hasher\MyCustomPasswordHasher'
This creates a hasher named app\_hasher from a service with the ID App\Security\Hasher\MyCustomPasswordHasher.

Supported Algorithms
auto
bcrypt
sodium
PBKDF2
Or create a custom password hasher
The "auto" Hasher
It automatically selects the best available hasher (currently Bcrypt). If PHP or Symfony adds new password hashers in the future, it might select a different hasher.

Because of this, the length of the hashed passwords may change in the future, so make sure to allocate enough space for them to be persisted (varchar(255) should be a good setting).

The Bcrypt Password Hasher
It produces hashed passwords with the bcrypt password hashing function. Hashed passwords are 60 characters long, so make sure to allocate enough space for them to be persisted. Also, passwords include the cryptographic salt inside them (it's generated automatically for each new password) so you don't have to deal with it.

Its only configuration option is cost, which is an integer in the range of 4-31 (by default, 13). Each single increment of the cost doubles the time it takes to hash a password. It's designed this way so the password strength can be adapted to the future improvements in computation power.

You can change the cost at any time — even if you already have some passwords hashed using a different cost. New passwords will be hashed using the new cost, while the already hashed ones will be validated using a cost that was used back when they were hashed.

A simple technique to make tests much faster when using BCrypt is to set the cost to 4, which is the minimum value allowed, in the test environment configuration.

The Sodium Password Hasher
It uses the Argon2 key derivation function. Argon2 support was introduced in PHP 7.2 by bundling the libsodium extension.

The hashed passwords are 96 characters long, but due to the hashing requirements saved in the resulting hash this may change in the future, so make sure to allocate enough space for them to be persisted. Also, passwords include the cryptographic salt inside them (it's generated automatically for each new password) so you don't have to deal with it.

The PBKDF2 Hasher
Using the PBKDF2 hasher is no longer recommended since PHP added support for Sodium and BCrypt. Legacy application still using it are encouraged to upgrade to those newer hashing algorithms.

Creating a custom Password Hasher
If you need to create your own, it needs to follow these rules:

The class must implement PasswordHasherInterface (you can also implement LegacyPasswordHasherInterface if your hash algorithm uses a separate salt);
The implementations of hash() and verify() must validate that the password length is no longer than 4096 characters. This is for security reasons (see CVE-2013-5750).

You can use the isPasswordTooLong() method for this check.

 Copy
// src/Security/Hasher/CustomVerySecureHasher.php
namespace App\Security\Hasher;

use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\PasswordHasher\Hasher\CheckPasswordLengthTrait;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;

class CustomVerySecureHasher implements PasswordHasherInterface
{
 use CheckPasswordLengthTrait;

 public function hash(string $plainPassword): string
 {
 if ($this->isPasswordTooLong($plainPassword)) {
 throw new InvalidPasswordException();
 }

 // ... hash the plain password in a secure way

 return $hashedPassword;
 }

 public function verify(string $hashedPassword, string $plainPassword): bool
 {
 if ('' === $plainPassword || $this->isPasswordTooLong($plainPassword)) {
 return false;
 }

 // ... validate if the password equals the user's password in a secure way

 return $passwordIsValid;
 }

 public function needsRehash(string $hashedPassword): bool
 {
 // Check if a password hash would benefit from rehashing
 return $needsRehash;
 }
}
Now, define a password hasher using the id setting:

 Copy
# config/packages/security.yaml
security:
 # ...
 password\_hashers:
 app\_hasher:
 # the service ID of your custom hasher (the FQCN using the default services.yaml)
 id:
[END CHUNK 2/3]
Reply with OK: [CHUNK x/TOTAL], don't reply anything else, don't explain the text!
[시작 청크 2/3]### test2.txt ###사용자 비밀번호 해셔 인터페이스{ // ... public function needsRehash(문자열 $hashed): bool { // 현재 비밀번호가 오래된 해셔를 사용하여 해시되었는지 확인합니다. $hashIsOutdated = ...; 반환 $hashIsOutdated; }}동적 비밀번호 해셔일반적으로 특정 클래스의 모든 인스턴스에 적용되도록 구성하여 모든 사용자에게 동일한 비밀번호 해셔를 사용합니다. 또 다른 옵션은 "명명된" 해셔를 사용한 다음 동적으로 사용할 해셔를 선택하는 것입니다.기본적으로(문서 시작 부분에 표시된 것처럼) 자동 알고리즘은 App\Entity\User에 사용됩니다.일반 사용자에게는 충분히 안전할 수 있지만, 관리자가 더 강력한 알고리즘(예: 더 높은 비용이 드는 자동)을 원한다면 어떻게 해야 할까요? 이는 네임드 해셔를 사용하여 수행할 수 있습니다: 복사# config/packages/security.yamlsecurity: # ... password\_hashers: harsh: algorithm: auto cost: 15이렇게 하면 harsh라는 이름의 해셔가 생성됩니다. User 인스턴스가 이 해셔를 사용하려면 클래스가 PasswordHasherAwareInterface를 구현해야 합니다. 이 인터페이스에는 사용할 해셔의 이름을 반환해야 하는 getPasswordHasherName() 메서드가 하나 필요합니다: Copy// src/Entity/User.php네임스페이스 App\Entity;사용 Symfony\Component\PasswordHasher\Hasher\PasswordHasherAwareInterface;사용 Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;사용 Symfony\Component\Security\Core\User\UserInterface;User 클래스 구현 UserInterface, 암호 인증 사용자 인터페이스를 구현합니다, PasswordHasherAwareInterface{ // ... 공개 함수 getPasswordHasherName(): ?string { if ($this->isAdmin()) { return 'harsh'; } return null; // 기본 해셔 사용 }}비밀번호를 마이그레이션할 때 레거시 해셔 이름을 반환하기 위해 PasswordHasherAwareInterface를 구현할 필요가 없습니다. Symfony는 마이그레이트\_from 구성에서 이를 감지합니다.PasswordHasherInterface를 구현하는 자체 암호 해셔를 만든 경우 이를 명명된 해셔로 사용하려면 해당 서비스를 등록해야 합니다: 복사# 구성/패키지/보안.yamlsecurity: # ... password\_hashers: 앱\_해셔: id: '앱\보안\해셔\내사용자 비밀번호해셔'이렇게 하면 서비스에서 앱\보안\해셔\마이커스텀패스워드해셔라는 이름의 해셔가 ID가 앱\보안\해셔\마이커스텀패스워드해셔로 생성됩니다.지원되는 알고리즘autobcryptsodiumPBKDF2또는 사용자 정의 비밀번호 해셔 생성"자동" 해셔사용 가능한 최상의 해셔(현재 Bcrypt)를 자동으로 선택합니다. 향후 PHP 또는 Symfony에서 새 비밀번호 해셔를 추가하면 다른 해셔를 선택할 수 있습니다.따라서 해시된 비밀번호의 길이가 향후 변경될 수 있으므로 비밀번호가 유지될 수 있도록 충분한 공간을 할당해야 합니다(varchar(255)가 좋은 설정입니다).Bcrypt 비밀번호 해셔bcrypt 비밀번호 해시 함수를 사용하여 해시된 비밀번호를 생성합니다. 해시된 비밀번호의 길이는 60자이므로 비밀번호가 유지될 수 있도록 충분한 공간을 할당해야 합니다. 또한, 비밀번호 내부에 암호화 솔트가 포함되어 있으므로(새 비밀번호를 생성할 때마다 자동으로 생성됨) 사용자가 직접 처리할 필요가 없습니다.유일한 구성 옵션은 4-31 범위의 정수인 비용입니다(기본값은 13). 비용이 1씩 증가할 때마다 비밀번호를 해시하는 데 걸리는 시간이 두 배로 늘어납니다. 이러한 방식으로 설계된 이유는 향후 연산 능력 향상에 따라 비밀번호 강도를 조정할 수 있도록 하기 위해서입니다.이미 다른 비용을 사용하여 일부 비밀번호를 해시한 경우에도 언제든지 비용을 변경할 수 있습니다. 새 비밀번호는 새로운 비용을 사용하여 해시되고, 이미 해시된 비밀번호는 해시될 때 사용했던 비용을 사용하여 유효성을 검사합니다.BCrypt를 사용할 때 테스트 속도를 훨씬 빠르게 만드는 간단한 방법은 테스트 환경 구성에서 비용을 허용되는 최소값인 4로 설정하는 것입니다.나트륨 비밀번호 해셔Argon2 키 파생 함수를 사용합니다. Argon2 지원은 PHP 7.2에서 libsodium 확장을 번들링하여 도입되었습니다.해시된 비밀번호의 길이는 96자이지만 결과 해시에 저장되는 해싱 요구 사항으로 인해 향후 변경될 수 있으므로 비밀번호가 지속될 수 있도록 충분한 공간을 할당해야 합니다. 또한 비밀번호에는 암호화 솔트가 포함되어 있으므로(새 비밀번호를 만들 때마다 자동으로 생성됨) 비밀번호를 일일이 관리할 필요가 없습니다.PBKDF2 해셔PHP에서 Sodium 및 BCrypt에 대한 지원이 추가되었으므로 PBKDF2 해셔를 사용하는 것은 더 이상 권장되지 않습니다. 여전히 이 해셔를 사용하는 레거시 애플리케이션은 최신 해싱 알고리즘으로 업그레이드하는 것이 좋습니다.사용자 정의 비밀번호 해셔 만들기사용자 정의 해셔를 직접 만들어야 하는 경우 다음 규칙을 따라야 합니다:클래스는 PasswordHasherInterface를 구현해야 합니다(해시 알고리즘이 별도의 솔트를 사용하는 경우 LegacyPasswordHasherInterface를 구현할 수도 있습니다);해시() 및 검증()의 구현은 비밀번호 길이가 4096자를 넘지 않는지 확인해야 합니다. 이는 보안상의 이유 때문입니다(CVE-2013-5750 참조).이 확인을 위해 isPasswordTooLong() 메서드를 사용할 수 있습니다. 복사// src/Security/Hasher/CustomVerySec