Forked from bizley/no-bullshit-password-validation.php
Created
March 14, 2017 01:52
-
-
Save egorsmkv/48c0348762ba0d1fe8251c0799f52003 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace app\models; | |
use yii\base\Model; | |
use Yii; | |
/** | |
* Simplified model with validation rules. | |
* All characters are allowed (you want emojis in the password? Go ahead). | |
* There are three basic rules for the user: | |
* 1) Minimum password length. | |
* 2) Minimum password entropy. | |
* 3) Don't use common names you see on the screen as password. | |
* | |
* @property string $email | |
*/ | |
class User extends Model | |
{ | |
const MIN_PASSWORD = 10; | |
const MAX_PASSWORD = 64; | |
const MIN_ENTROPY = 2; | |
/** | |
* @var string Raw password to be validated | |
*/ | |
public $rawPassword; | |
/** | |
* @inheritdoc | |
*/ | |
public function rules() | |
{ | |
return [ | |
// obviously we need these 2 | |
[['email', 'rawPassword'], 'required'], | |
// email should be email, also Yii 2 limits max email size to 254 characters so we don't have to worry about that | |
['email', 'email'], | |
// email needs to be unique in database to identify user | |
['email', 'unique'], | |
// password must not be shorter than self::MIN_PASSWORD | |
// 10 characters minimum is required nowadays | |
// but it shouldn't be a problem especially when we don't force bullshit composition | |
// maximum limit is not that important but we should add reasonable one as well | |
['rawPassword', 'string', 'min' => self::MIN_PASSWORD, 'max' => self::MAX_PASSWORD], | |
// lazy copy-paste check: password must not be the same as user's email address | |
['rawPassword', 'compare', 'compareAttribute' => 'email', 'operator' => '!='], | |
// lazy copy-paste check: password must not be the same as application's name | |
['rawPassword', 'compare', 'compareValue' => Yii::$app->name, 'operator' => '!='], | |
// lazy copy-paste check: password must not be the same as application's URL | |
['rawPassword', 'compare', 'compareValue' => \yii\helpers\Url::home(), 'operator' => '!='], | |
// password's entropy must be greater than self::MIN_ENTROPY (the smaller number = more repetition allowed) | |
// some examples: 'aaaaaaaaaa' => 0, '0123456789' => 3.322 | |
['rawPassword', function ($attribute, $params, $validator) { | |
$entropy = 0; | |
$size = mb_strlen($this->$attribute, Yii::$app->charset ?: 'UTF-8'); | |
foreach (count_chars($this->$attribute, 1) as $frequency) { | |
$p = $frequency / $size; | |
$entropy -= $p * log($p) / log(2); | |
} | |
if ($entropy < self::MIN_ENTROPY) { | |
$this->addError($attribute, 'You must choose more complex password.'); | |
} | |
}], | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment