У меня имеются две модели форм:
1) (PasswordResetRequestForm) Форма для ввода email, на который придет ссылка с восстановлением (типа /change-password?token=token_value, токен генерируется)
2) (PasswordChangeForm) Форма для смены пароля, в запрос принимается get-параметр токена
Как логика работы форм реализована на данный момент:
Контроллер:
Код: Выделить всё
public function actionResetPasswordRequest()
{
$model = new PasswordResetRequestForm();
if(Yii::$app->request->Post('PasswordResetRequestForm'))
{
$model->attributes = Yii::$app->request->Post('PasswordResetRequestForm');
if($model->validate())
{
define("EXPIRE_TIME", 30); //время в минутах, после которого токен считается не валидным
$user = User::findOne(['user_email' => $model->email]);//получаем пользователя по имейлу
//формирование записи в таблице reset_password_token
$resetPasswordToken = new ResetPasswordToken();
$resetPasswordToken->user_id = $user->user_id;
$resetPasswordToken->token = sha1(mt_rand(10000, 99999).time());//генерация рандомного токена
$resetPasswordToken->expires = Date('Y-m-d h:i:s', strtotime("+".EXPIRE_TIME." minutes"));
$resetUrl = Url::base(true).Url::toRoute(['/change-password', 'token' => $resetPasswordToken->token]);
if($resetPasswordToken->save())
{
SendEmail::sendResetPasswordMail($model->email, $resetUrl);
}
return $this->render('ResetSuccess');
}
}
return $this->render('PasswordResetRequestForm', ['model'=>$model]);
}
public function actionChangePassword($token = false)
{
$message = 'Ваша ссылка восстановления не действительна';
if($token) //если token получен, то производим восстановление пароля
{
$model = new PasswordChangeForm();
$resetPasswordToken = ResetPasswordToken::findOne(['token' => $token]);
//проверка наличия и валидности токена
if($resetPasswordToken && ! $resetPasswordToken->expires())
{
if(Yii::$app->request->post('PasswordChangeForm'))
{
$model->attributes = Yii::$app->request->post('PasswordChangeForm');
if($model->validate())
{
$model->changeUserPassword($resetPasswordToken);
return $this->render('ChangeSuccess');
}
}
return $this->render('PasswordChange', ['model' => $model]);
}
$message = 'Срок действия вашей уникальной ссылки истек. Срок действия - 30 минут с момента получения';
}
return $this->render('@app/views/site/error',
[
'name'=>'Ошибка валидации',
'message'=>$message,
]
);
}
В actionChangePassword(), происходит проверка "! $resetPasswordToken->expires()", этот метод прописан в AR модели таблицы reset_password_token:
Код: Выделить всё
/*
Возвращает true, если время действия токена истекло
*/
public function expires()
{
$currentDate = Date('Y-m-d h:i:s');
$expiresDate = $this->expires;
if( $expiresDate < $currentDate )
{
return true;
}
return false;
}