/
PasswordValidator.php
93 lines (81 loc) · 2.67 KB
/
PasswordValidator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<?php
/**
* This class represents a validator for member passwords.
*
* <code>
* $pwdVal = new PasswordValidator();
* $pwdValidator->minLength(7);
* $pwdValidator->checkHistoricalPasswords(6);
* $pwdValidator->characterStrength('lowercase','uppercase','digits','punctuation');
*
* Member::set_password_validator($pwdValidator);
* </code>
*
* @package sapphire
* @subpackage security
*/
class PasswordValidator extends Object {
static $character_strength_tests = array(
'lowercase' => '/[a-z]/',
'uppercase' => '/[A-Z]/',
'digits' => '/[0-9]/',
'punctuation' => '/[^A-Za-z0-9]/',
);
protected $minLength, $minScore, $testNames, $historicalPasswordCount;
/**
* Minimum password length
*/
function minLength($minLength) {
$this->minLength = $minLength;
}
/**
* Check the character strength of the password.
*
* Eg: $this->characterStrength(3, array("lowercase", "uppercase", "digits", "punctuation"))
*
* @param $minScore The minimum number of character tests that must pass
* @param $testNames The names of the tests to perform
*/
function characterStrength($minScore, $testNames) {
$this->minScore = $minScore;
$this->testNames = $testNames;
}
/**
* Check a number of previous passwords that the user has used, and don't let them change to that.
*/
function checkHistoricalPasswords($count) {
$this->historicalPasswordCount = $count;
}
/**
* @param String $password
* @param Member $member
* @return ValidationResult
*/
function validate($password, $member) {
$valid = new ValidationResult();
if($this->minLength) {
if(strlen($password) < $this->minLength) $valid->error(sprintf("Password is too short, it must be %s or more characters long.", $this->minLength), "TOO_SHORT");
}
if($this->minScore) {
$score = 0;
$missedTests = array();
foreach($this->testNames as $name) {
if(preg_match(self::$character_strength_tests[$name], $password)) $score++;
else $missedTests[] = $name;
}
if($score < $this->minScore) {
$valid->error("You need to increase the strength of your passwords by adding some of the following characters: " . implode(", ", $missedTests), "LOW_CHARACTER_STRENGTH");
}
}
if($this->historicalPasswordCount) {
$previousPasswords = DataObject::get("MemberPassword", "\"MemberID\" = $member->ID", "\"Created\" DESC, \"ID\" Desc", "", $this->historicalPasswordCount);
if($previousPasswords) foreach($previousPasswords as $previousPasswords) {
if($previousPasswords->checkPassword($password)) {
$valid->error("You've already used that password in the past, please choose a new password", "PREVIOUS_PASSWORD");
break;
}
}
}
return $valid;
}
}