Подтверждение пароля php
Мне любопытно знать: как только токен pw_reset отправляется по электронной почте, можно ли получить адрес электронной почты учетной записи реферала для проверки или лучше проверить по IP? Я установил срок действия моего токена всего на 1 час, и даже динамические IP-адреса не меняются с такой скоростью, верно?
Некоторый код, с которым я играю (очень много WIP), открыт для улучшений / предложений / критики.
Заранее спасибо.
/**
* Reset Password Form
*
* $route['auth/reset-password'] = 'reset_password_form';
*
*/
public function reset_password_form()
{
$this->load->view('templates/public', array(
'content' => 'auth/reset_password_form',
'title' => 'Password reset',
'description' => '',
'canonical' => 'auth'
));
}
/**
* Reset Password Authentication
*
* $route['auth/reset_password/validate'] = 'auth/reset_password';
*
*/
public function reset_password()
{
//setup validation rules
$config = array(
array('field'=>'email_address', 'label' =>'Email address', 'rules'=>'trim|required|max_lenght[128]|valid_email|valid_user_email')
);
$this->form_validation->CI =& $this;
$this->form_validation->set_rules($config);
//run validator and confirm OR
if($this->form_validation->run($this))
{
//create the token data
$tokenhash = Auth::create_token();
$password_token = json_encode(array(
'token' => $tokenhash,
'expires' => date('h:i:s A', strtotime($this->config->item('pw_token_expires'))), // default 1 hours
'ip_address' => $this->input->ip_address()
)); // output {"token":"3513f5ee34ED3","expires":"01:14:06 AM","ip_address":"127.0.0.1"}
//grab a userid to use via php-activerecord custom USER model
$user = User::get_by_email_address($this->input->post('email_address'));
//update the user pw_token field
try{
if($user->update_attribute('pw_token', $password_token))
{
throw new \ActiveRecord\ActiveRecordException($user->errors);
}
}catch(\ActiveRecord\ActiveRecordException $e){
log_message('error', $e->getMessage());
}
//setup email data
//TODO : move this to USER activeRecord\Model (pre_)
$email_data = array(
'email_to' => $user->email_address,
'token' => anchor(site_url('auth/reset_password/confirm/'.$tokenhash.'/'.$user->id.''), 'click here to reset your password'),
'site_link' => anchor(site_url(), site_url())
);
try{
if(Mail::send($email_data, 'reset_password.tpl.html'))
{
throw new Exception(Mail::errors());
}
}catch(Exception $e){
log_message('error', $e->getMessage());
}
}
else
{
$this->reset_password_form();
}
}
/**
* Reset Password Confirmation
*
* $route['auth/reset_password/confirm/(:any)/(:num)'] = 'auth/confirm_password_reset';
*/
public function confirm_password_reset($token='', $userid='')
{
//check for null values
if(!$token || !$id)
{
redirect('/');
}
//ugly
$attempts = $this->session->set_userdata('reset_pw_attempt', (int)0);
$this->session->set_userdata('reset_pw_attempts', $attempts++);
if(!$this->user->id != $userid && $this->session->userdata('logged_in') === (int)0)
{
//not great but cant validate the email, so we check to see if they have a logged in session.
//this is not a "forgot_password request" so we should be good as long as they are logged in
show_404();
}
else
{
//looking good so far, now lets see do they have the correct permissions
if(in_array(PERM_UPDATE, Auth::permissions($this->user->permissions)))
{
if($attempts == (int)3)
{
$this->session->set_flashdata('', $this->lang->line('pw_reset_attempt_over'));
redirect('/');
}
else
{
$tokn[] = json_decode($this->user->pw_token);
if(date('h:i:s A', time()) > $tokn['expires'] && $token===$tokn['token'])
{
$this->load->view('do-pw_reset_form');
}
}
}
else
{
$this->session->set_flashdata('info', $this->lang->line('update_permission_denied'));
redirect('/');
}
}
}
3 ответа
Проверка адреса электронной почты с помощью параметра строки запроса или использование ограничения IP-адресов являются совершенно излишними. Если токен пароля является случайным и достаточно длинным, его невозможно будет перебором, особенно в сочетании с истечением токена И ограничением скорости предположений токена.
Ограничение IP-адреса также может быть проблемой удобства использования. Например, пользователь может запросить сброс пароля непосредственно перед уходом с работы, а затем завершить процесс сброса из дома или во время поездки домой - то есть IP-адрес пользователя изменяется между запросом сброса и подтверждением сброса.
Почему вы хотите проверить реферер? Использование проверки с обратной связью является стандартной практикой для подтверждения адресов электронной почты пользователей. Вам не нужно проверять IP или реферала, все, что вам нужно сделать, это создать собственный хэш и отследить адрес электронной почты, а затем отправить электронное письмо с этой информацией пользователю.
Когда пользователь щелкает по встроенной ссылке, вы затем подтверждаете созданный вами хеш, если хэш выстраивается в линию, то пользователь подтверждает свою учетную запись электронной почты в вашей системе.
//Example Link
https://mydomain.com/verify?hash=<some_hash>
Для дополнительной безопасности вы также можете отследить время, когда ваша система отправила электронное письмо, и аннулировать хеш через 24 часа. Поэтому, если пользователь щелкает по истечении 25 часов, вы сообщаете ему, что хеш-код недействителен, и спрашиваете, хотят ли они отправить еще одно электронное письмо, если это так, повторите описанную выше процедуру.
Нет смысла проверять реферера, если компьютер клиента скомпрометирован, вы ничего не можете сделать, чтобы избежать угона. Что вы можете сделать, так это следить за уязвимостями CSRF.
Кроме того, после прочтения он выглядит так, как будто он проверяет 'ip_address' => $this->input->ip_address().