In Craft 2
Plugins have the power to enforce stricter password requirements using the users.onBeforeSetPassword event.
Add this code to your plugin’s primary class:
public function init()
{
craft()->on('users.beforeSetPassword', array($this, 'onBeforeSetPassword'));
}
public function onBeforeSetPassword(Event $e)
{
$user = $e->params['user'];
$password = $e->params['password'];
// Perform our custom validation logic here
$validates = true;
if (mb_strlen($password) < 7)
{
$validates = false;
}
else if (!preg_match('/(\d.*[A-Z]|[A-Z].*\d)/', $password))
{
$validates = false;
}
if (!$validates)
{
// Set $performAction = false so the password doesn't get saved
$e->performAction = false;
// Add a custom validation error on the user
$user->addError('newPassword', 'Sorry but your password must contain an uppercase letter, a number, a haiku, a gang sign, hieroglyph, and the blood of a virgin.');
}
}
In Craft 3
Craft 3 doesn't have a beforeSetPassword
event, but you can pull the same thing off from your plugin's init() method using the User element's User::EVENT_BEFORE_VALIDATE
event like so:
public function init()
{
parent::init();
Event::on(
User::class,
User::EVENT_BEFORE_VALIDATE,
function (ModelEvent $event) {
// Check if a new password was set on the user
if ($event->sender->newPassword) {
$password = $event->sender->newPassword;
$errors = [];
// Perform our custom validation logic here
$validates = true;
if (mb_strlen($password) < 7) {
$validates = false;
$errors[] = 'Too Short!';
}
else if (!preg_match('/(\d.*[A-Z]|[A-Z].*\d)/', $password)) {
$validates = false;
$errors[] = 'Too Simple!';
}
$event->isValid = $validates;
if (!$validates) {
/** @var User $user */
$user = $event->sender;
foreach ($errors as $error) {
$user->addError('newPassword', $error);
}
}
}
}
);
}