2016-10-01 233 views
2

我在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('[email protected]', 'Your Name'); 
       $this->email->to('[email protected]'); 
       $this->email->subject($reset_code); 
       $this->email->message(
        'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'&code='.urlencode($temp_pass).'&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 && $temp_pass && $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)).'&code='.urlencode($this->input->get('code', true)).'&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

我希望你已經完成了加密和解密,以使密碼安全。 –

+0

是的。這是對的。 – Vikas

+1

我還會添加使用密碼重置的時間限制。 – cssBlaster21895

回答

1

我讀過你的代碼,我想即使我添加了使用新令牌的時間限制,它仍然不安全。根據owasp cheatsheat on password recovery,你可以做得比這更好。我爲你縮短一點。他們說出五點。

  1. 使用您在用戶註冊過程中收集一些數據 - 它可以是生日,手機號碼,姓氏等
  2. 使用的安全性問題,並把答案輸入爲純文本,不做下拉或類似的東西。在這裏限制猜測的數量。在構建這些問題時不是微不足道的和創造性的。
  3. 第二步之後,建議分別鎖定用戶帳號。生成有時間限制的密碼令牌,並通過不同的通信渠道(可能使用短信或輔助電子郵件)發送(至少嘗試)。
  4. 注意會話,只允許在當前會話期間重置密碼。在這一步加強密碼複雜性(你可以使用一些jQuery插件)。
  5. 嘗試記錄用戶操作,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('[email protected]', 'Your Name'); 
      $this->email->to('[email protected]'); 
      $this->email->subject($reset_code); 
      $this->email->message(
       'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'&code='.urlencode($temp_pass).'&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 && $temp_pass && $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 && $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('/'); 
    } 
} 
+0

感謝您的建議... – Vikas

+1

振作起來,ci最受歡迎的auth庫也不是那麼嚴格。我可以寫這段代碼,但後來:)現在你可以看一眼https://github.com/benedmunds/CodeIgniter-Ion-Auth/blob/2/libraries/Ion_auth.php#L274,你可以做相似的東西。 – cssBlaster21895

+0

感謝您的代碼。 – Vikas