#php #mysql #codeigniter
#php #mysql #codeigniter
Вопрос:
Я написал пароль пользователя и код отправки по электронной почте в codeignter.
Я создал контроллер для восстановления пароля. Мой код отправляет временный пароль по электронной почте с полученным URL, и я проверяю этот URL и сохраняю новый пароль в базе данных.
Теперь, как я могу сделать этот код более безопасным и надежным.
мой контроллер:
public function recover(){
$data['main_content'] = 'auth/recover';
$this->load->view('public/layouts/home_main', $data);
}
public function recover_account(){
$this->form_validation->set_rules('username','Username','trim|xss_clean|required');
if ($this->form_validation->run() == FALSE){
//Show View
$data = array(
'errors' => validation_errors()
);
$this->session->set_flashdata($data);
$data['main_content'] = 'auth/recover';
$this->load->view('public/layouts/home_main', $data);
}
else{
$account = $this->input->post('username');
if($this->User_model->user_exist($account)){
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$temp_pass = password_hash(rand(23456,975655), PASSWORD_BCRYPT, $options);
$reset_code = rand(23456,975655);
$data = array(
'reset_link_code' => $reset_code
);
$this->session->set_userdata($data);
$this->email->from('info@netbeam.in', 'Your Name');
$this->email->to('vikas@onusworld.com');
$this->email->subject($reset_code);
$this->email->message(
'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'amp;code='.urlencode($temp_pass).'amp;rstc='.urlencode($reset_code).'">Click Here</a>'
);
$db_pass = array(
'password' => $temp_pass
);
$this->db->where('email', $account);
$this->db->or_where('username', $account);
$this->db->update('users', $db_pass);
if($this->email->send()){
echo 'Passowrd resend link sent to email';
}else{
echo 'email count not check, pls talk to support';
}
}else{
echo "User not Fount";
}
}
}
function reset_password(){
$email = urldecode($this->input->get('user', true));
$temp_pass = urldecode($this->input->get('code', true));
$reset_code = urldecode($this->input->get('rstc', true));
if($email amp;amp; $temp_pass amp;amp; $reset_code){
$this->form_validation->set_rules('user','Username','trim|xss_clean|min_length[4]');
$this->form_validation->set_rules('newpass','Password','trim|xss_clean|required|min_length[4]|max_length[50]');
$this->form_validation->set_rules('newpass2','Confirm Password','trim|xss_clean|required|matches[newpass]');
if($reset_code == $this->session->userdata('reset_link_code')){
$db_pass = $this->User_model->get_heshed_password($email);
if($temp_pass == $db_pass){
if ($this->form_validation->run() == FALSE){
//Show View
$data = array(
'errors' => validation_errors()
);
$this->session->set_flashdata($data);
$data['main_content'] = 'auth/reset_password';
$this->load->view('public/layouts/home_main', $data);
}
else{
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$password = $this->input->post('newpass');
$passtodb = password_hash($password, PASSWORD_BCRYPT, $options);
$data = array(
'password' => $passtodb
);
$this->db->where('email', $email);
$this->db->or_where('username', $email);
$this->db->update('users', $data);
redirect('account');
}
}
}else{
echo 'invalid reset code';
}
}else{
redirect('/');
}
}
мои файлы просмотра:
<?php if(!$this->session->userdata('logged_in')) : ?>
<section style="background:#ccc;padding-top:20px;">
<div class="container">
<div class="col-md-10 col-md-offset-1">
<div class="coupon-area">
<div class="container-fluid">
<div class="col-md-12">
<div class="col-md-9 col-md-offset-1 ac-form-login">
<h4 class="modal-title">Recover Password</h4>
<hr class="separator">
<br>
<?php if($this->session->flashdata('errors')) : ?>
<div class="alert alert-danger">
<?php echo $this->session->flashdata('errors'); ?>
</div>
<?php endif; ?>
<div>
<form class="form-horizontal" action="<?php echo base_url(); ?>auth/recover_account" method="post">
<div class="form-group">
<div class="col-sm-8">
<input type="text" name="username" class="form-input-modal" placeholder="Enter your registered email" required>
</div>
</div>
<div class="form-group">
<div class=" col-sm-6">
<button type="submit" class="btn btn-default">Recover Password</button>
</div>
</div>
</form>
</div>
<br>
<hr class="separator">
<br>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<?php else: ?>
<?php redirect('account'); ?>
<?php endif; ?>
моя форма сброса пароля:
<?php if(!$this->session->userdata('loged_i')):?>
<section style="background:#ccc;padding-top:20px;">
<div class="container">
<div class="col-md-10 col-md-offset-1">
<div class="coupon-area">
<div class="container-fluid">
<div class="col-md-12">
<div class="col-md-9 col-md-offset-1 ac-form-login">
<h4 class="modal-title">Recover Password</h4>
<hr class="separator">
<br>
<?php if($this->session->flashdata('errors')) : ?>
<div class="alert alert-danger">
<?php echo $this->session->flashdata('errors'); ?>
</div>
<?php endif; ?>
<div>
<form class="form-horizontal" action="<?php echo base_url(); ?>auth/reset_password?user=<?php echo urlencode($this->input->get('user', true)).'amp;code='.urlencode($this->input->get('code', true)).'amp;rstc='.urlencode($this->input->get('rstc', true));?>" method="post">
<div class="form-group">
<div class="col-sm-8">
<input type="text" name="user" class="form-input-modal form-control" value="<?php echo urldecode($this->input->get('user', true));?>" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-8">
<input type="password" name="newpass" class="form-input-modal" placeholder="Set Password" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-8">
<input type="password" name="newpass2" class="form-input-modal" placeholder="Confirm Set Password" required>
</div>
</div>
<div class="form-group">
<div class=" col-sm-6">
<button type="submit" class="btn btn-default">Reset Password</button>
</div>
</div>
</form>
</div>
<br>
<hr class="separator">
<br>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<?php else: ?>
<?php redirect('account'); ?>
<?php endif; ?>
Моя проблема в том, что я хочу сделать этот код более удобным для пользователя и безопасным, чтобы я мог предотвратить внедрение SQL и другие проблемы.
Комментарии:
1. Я надеюсь, вы выполнили шифрование и дешифрование, чтобы сделать пароли безопасными.
2. да. это правильно.
3. Я бы также добавил ограничение по времени для использования сброса пароля.
4. @cssBlaster21895 спасибо за комментарий. можете ли вы внести изменения в код?
Ответ №1:
Я прочитал ваш код и думаю, что даже если я добавлю ограничение по времени для использования нового токена, он все равно не будет безопасным. Согласно owasp cheatsheat по восстановлению пароля, вы можете сделать лучше. Я немного сокращаю его для вас. Они называют пять пунктов.
- Используйте некоторые данные, которые вы собрали в процессе регистрации пользователя — это может быть день рождения, номер мобильного телефона, фамилия и т.д.
- Используйте контрольные вопросы и вводите ответы в виде чистого текста, не делайте выпадающий список или что-то в этом роде. Ограничьте здесь количество догадок. Будьте нетривиальны и изобретательны в построении этих вопросов.
- После второго шага рекомендуется заблокировать учетную запись пользователя imidiatelly. Сгенерируйте токен пароля с ограниченным временем и отправьте его (по крайней мере, попытайтесь) по другому каналу связи, возможно, с помощью sms или на дополнительную электронную почту.
- Следите за сеансом и разрешайте сброс пароля только во время текущего сеанса. На этом шаге примените сложность пароля (для этого вы можете использовать какой-нибудь плагин jquery).
- Попробуйте записать действия пользователя, IP-адрес, данные браузера. Сосредоточьтесь на неудачных попытках или использовании токенов с истекшим сроком действия. Таким образом, вы можете отслеживать вредоносное поведение и делать некоторые выводы.
И вот мое небольшое обновление. Я использую столбец updated_at, который может быть полезен во многих других ситуациях, или вы можете указать свой собственный столбец только для ограничения времени сброса пароля.
<?php
public function recover(){
$data['main_content'] = 'auth/recover';
$this->load->view('public/layouts/home_main', $data);
}
public function recover_account(){
$this->form_validation->set_rules('username','Username','trim|xss_clean|required');
if ($this->form_validation->run() == FALSE){
//Show View
$data = array(
'errors' => validation_errors()
);
$this->session->set_flashdata($data);
$data['main_content'] = 'auth/recover';
$this->load->view('public/layouts/home_main', $data);
}
else{
$account = $this->input->post('username');
if($this->User_model->user_exist($account)){
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$temp_pass = password_hash(rand(23456,975655), PASSWORD_BCRYPT, $options);
$reset_code = rand(23456,975655);
$data = array(
'reset_link_code' => $reset_code
);
$this->session->set_userdata($data);
$this->email->from('info@netbeam.in', 'Your Name');
$this->email->to('vikas@onusworld.com');
$this->email->subject($reset_code);
$this->email->message(
'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'amp;code='.urlencode($temp_pass).'amp;rstc='.urlencode($reset_code).'">Click Here</a>'
);
$db_pass = array(
'password' => $temp_pass,
'updated_at' => time() //or even date("Y-m-d H:i:s")
);
$this->db->where('email', $account);
$this->db->or_where('username', $account);
$this->db->update('users', $db_pass);
if($this->email->send()){
echo 'Passowrd resend link sent to email';
}else{
echo 'email count not check, pls talk to support';
}
}else{
echo "User not Fount";
}
}
}
function reset_password(){
$email = urldecode($this->input->get('user', true));
$temp_pass = urldecode($this->input->get('code', true));
$reset_code = urldecode($this->input->get('rstc', true));
if($email amp;amp; $temp_pass amp;amp; $reset_code){
$this->form_validation->set_rules('user','Username','trim|xss_clean|min_length[4]');
$this->form_validation->set_rules('newpass','Password','trim|xss_clean|required|min_length[4]|max_length[50]');
$this->form_validation->set_rules('newpass2','Confirm Password','trim|xss_clean|required|matches[newpass]');
if($reset_code == $this->session->userdata('reset_link_code')){
//get user data by email
//$user = $this->User_model->get_heshed_password($email);
$user = $this->User_model->get_heshed_password_and_updated_value($email);
//calculate time difference
$dbdate = strtotime($user->updated_at);
if (time() - $dbdate > 15 * 60) {
// 15 mins has passed
$time_allowed = false;
} else {
$time_allowed = true;
}
if($temp_pass == $user->password amp;amp; $time_allowed){
if ($this->form_validation->run() == FALSE){
//Show View
$data = array(
'errors' => validation_errors()
);
$this->session->set_flashdata($data);
$data['main_content'] = 'auth/reset_password';
$this->load->view('public/layouts/home_main', $data);
}
else{
$options = [
'cost' => 8,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$password = $this->input->post('newpass');
$passtodb = password_hash($password, PASSWORD_BCRYPT, $options);
$data = array(
'password' => $passtodb
);
$this->db->where('email', $email);
$this->db->or_where('username', $email);
$this->db->update('users', $data);
redirect('account');
}
}
}else{
echo 'invalid reset code';
}
}else{
redirect('/');
}
}
Комментарии:
1. Не унывайте, самая популярная библиотека аутентификации для ci также не такая строгая. Я могу написать этот фрагмент кода, но позже 🙂 На данный момент вы можете взглянуть github.com/benedmunds/CodeIgniter-Ion-Auth/blob/2/libraries /… , вы можете сделать что-то подобное.