File tree Expand file tree Collapse file tree 3 files changed +41
-8
lines changed
Filter options
src/Symfony/Component/Validator Expand file tree Collapse file tree 3 files changed +41
-8
lines changed
Original file line number Diff line number Diff line change @@ -40,12 +40,16 @@ final class PasswordStrength extends Constraint
40
40
41
41
public int $ minScore ;
42
42
43
- public function __construct (int $ minScore = self :: STRENGTH_REASONABLE , mixed $ options = null , array $ groups = null , mixed $ payload = null )
43
+ public function __construct (array $ options = null , int $ minScore = null , array $ groups = null , mixed $ payload = null )
44
44
{
45
- if (isset ($ minScore ) && (!\is_int ($ minScore ) || $ minScore < 1 || $ minScore > 4 )) {
46
- throw new ConstraintDefinitionException (sprintf ('The parameter "minScore" of the "%s" constraint must be an integer between 1 and 4. ' , static ::class));
47
- }
48
- $ options ['minScore ' ] = $ minScore ;
45
+ $ options ['minScore ' ] ??= self ::STRENGTH_REASONABLE ;
46
+
49
47
parent ::__construct ($ options , $ groups , $ payload );
48
+
49
+ $ this ->minScore = $ minScore ?? $ this ->minScore ;
50
+
51
+ if ($ this ->minScore < 1 || 4 < $ this ->minScore ) {
52
+ throw new ConstraintDefinitionException (sprintf ('The parameter "minScore" of the "%s" constraint must be an integer between 1 and 4. ' , self ::class));
53
+ }
50
54
}
51
55
}
Original file line number Diff line number Diff line change @@ -58,7 +58,26 @@ public function validate(#[\SensitiveParameter] mixed $value, Constraint $constr
58
58
*/
59
59
private static function estimateStrength (#[\SensitiveParameter] string $ password ): int
60
60
{
61
- $ entropy = log (\strlen (count_chars ($ password , 3 )) ** \strlen ($ password ), 2 );
61
+ if (!$ length = \strlen ($ password )) {
62
+ return PasswordStrength::STRENGTH_VERY_WEAK ;
63
+ }
64
+ $ password = count_chars ($ password , 1 );
65
+ $ chars = \count ($ password );
66
+
67
+ $ control = $ digit = $ upper = $ lower = $ symbol = $ other = 0 ;
68
+ foreach ($ password as $ chr => $ count ) {
69
+ match (true ) {
70
+ $ chr < 32 || 127 === $ chr => $ control = 33 ,
71
+ 48 <= $ chr && $ chr <= 57 => $ digit = 10 ,
72
+ 65 <= $ chr && $ chr <= 90 => $ upper = 26 ,
73
+ 97 <= $ chr && $ chr <= 122 => $ lower = 26 ,
74
+ 128 <= $ chr => $ other = 128 ,
75
+ default => $ symbol = 33 ,
76
+ };
77
+ }
78
+
79
+ $ pool = $ lower + $ upper + $ digit + $ symbol + $ control + $ other ;
80
+ $ entropy = $ chars * log ($ pool , 2 ) + ($ length - $ chars ) * log ($ chars , 2 );
62
81
63
82
return match (true ) {
64
83
$ entropy >= 120 => PasswordStrength::STRENGTH_VERY_STRONG ,
Original file line number Diff line number Diff line change @@ -30,12 +30,22 @@ public function testValidValues(string $value, int $expectedStrength)
30
30
$ this ->validator ->validate ($ value , new PasswordStrength (minScore: $ expectedStrength ));
31
31
32
32
$ this ->assertNoViolation ();
33
+
34
+ if (PasswordStrength::STRENGTH_VERY_STRONG === $ expectedStrength ) {
35
+ return ;
36
+ }
37
+
38
+ $ this ->validator ->validate ($ value , new PasswordStrength (minScore: $ expectedStrength + 1 ));
39
+
40
+ $ this ->buildViolation ('The password strength is too low. Please use a stronger password. ' )
41
+ ->setCode (PasswordStrength::PASSWORD_STRENGTH_ERROR )
42
+ ->assertRaised ();
33
43
}
34
44
35
45
public static function getValidValues (): iterable
36
46
{
37
- yield ['How-is this 🤔?! ' , PasswordStrength::STRENGTH_WEAK ];
38
- yield ['Reasonable-pwd-❤️ ' , PasswordStrength::STRENGTH_REASONABLE ];
47
+ yield ['How-is- this ' , PasswordStrength::STRENGTH_WEAK ];
48
+ yield ['Reasonable-pwd ' , PasswordStrength::STRENGTH_REASONABLE ];
39
49
yield ['This 1s a very g00d Pa55word! ;-) ' , PasswordStrength::STRENGTH_VERY_STRONG ];
40
50
yield ['pudding-smack-👌🏼-fox-😎 ' , PasswordStrength::STRENGTH_VERY_STRONG ];
41
51
}
You can’t perform that action at this time.
0 commit comments