reCaptcha - 强力保护(php / codeIgniter)

时间:2014-06-13 20:08:43

标签: php codeigniter security recaptcha brute-force

我在登录表单中添加了一个reCaptcha字段,当尝试使用相同的用户名时,> 5。 没有cookie,我有问题这样做。如果有人有想法,欢迎你。


这是我的伪代码:

  • 用户进入页面,计数器设置为failed_login = 0
  • 尝试登录时,如果用户猜错用户名但密码错误,则此用户名的db字段会增加
  • 当计数器是> 5,在登录页面

    上显示验证码

    我遇到的问题是即使计数器是> 5,我的控制器未验证验证码字段。而且,用户可能只是离开我的网站并回来让它的计数器回到0.这是否可以不使用cookie?我想有一个简单的方法。如果我使用cookie,也许可以检查用户是否在不久前清除了他的cookie,并显示验证码,任何想法欢迎 https://www.dropbox.com/s/30mf4ha1rm7w407/still_login.png

    我将在下面发布我的完整代码

    控制器

    public function index()
    {
        $data['publickey'] = "6LczHPd2USAAAAAbffN2Po1HaNqPyfdfdfdfdsRfaDPO9E-"; // for reCaptcha
    
        $this->form_validation->set_error_delimiters('<div class="alert alert-danger">', '</div>');
    
        $this->form_validation->set_rules('email', 'lang:label_email', 'required');
        $this->form_validation->set_rules('password', 'lang:label_password', 'required');
    
    
        global $nb_failed_attempt;
        $data['show_captcha'] = FALSE;
    
    
        if ($this->form_validation->run() === FALSE)
        {
            $this->load->view('templates/header', $data);
            $this->load->view('templates/topMenu', $data);
            $this->load->view('pages/login', $data);
    
        }
        else
        {
            #check login
            $success = $this->User_model->checkLogin($this->input->post('email'), $this->input->post('password'));
    
            #sucess redirect to home page
            if ($success) {
                redirect('/');
            }
            # bad login, reload page with error message
            else {
    
                echo $nb_failed_attempt;  ## variable not defined even when it is global inside user_model.php?
    
                if ($nb_failed_attempt > 5) {
                    $data['show_captcha'] = TRUE;
                    $this->form_validation->set_rules('recaptcha_challenge_field', 'Challenge', 'trim|required|callback_captcha_check');
                    # this doesnt get triggered even when >5, no captcha filled and with good pw you can still login..
                }
                else {
                    $data['show_captcha'] = FALSE;
                }
    
                $this->load->view('templates/header', $data);
                $this->load->view('templates/topMenu', $data);
                $this->load->view('pages/login', $data);
            }
        }
    }
    
    
    public function captcha_check($string) {
    
        $privatekey = "6LczHPUSAAAAAKQ58YZoV8S8ZCZ6A4ZiuqxSbbK5";
        $resp = recaptcha_check_answer ($privatekey,
                $_SERVER["REMOTE_ADDR"],
                $_POST["recaptcha_challenge_field"],
                $_POST["recaptcha_response_field"]);
    
        if (!$resp->is_valid) {
            $this->form_validation->set_message('captcha_check', 'The reCAPTCHA wasn\'t entered correctly. Go back and try it again.');
            return FALSE;
        } else {
            return TRUE;
        }
    }
    

    User_Model(db request)

       public function checkLogin($email, $password) {
    
    
        global $nb_failed_attempt; 
        if (!isset($nb_failed_attempt)) {
            $nb_failed_attempt = 0;
        }
    
            #retrieve the user salt
            $query1 = $this->db->get_where ( 'user', array ('email' => $email), 1, 0 );
    
    
            if ($query1->num_rows () <= 0) {
                $this->messages->add ( sprintf ( lang ( 'error_log_in' ), 'not_exist' ), "error" );
                return false;
            }
            else {
                if ($query1->first_row ()->confirm_code != 'y') {
                    $this->messages->add ( sprintf ( lang ( 'error_log_in' ), 'not yet activated' ), "error" );
                    return false;
                }
            }
    
            $salt = $query1->first_row ()->salt;
    
            // check for hashed password
            $saltedPW = $password . $salt;
            $hashedPW = hash ( 'sha256', $saltedPW );
    
    
            $query2 = $this->db->get_where ( 'user', array ('email' => $email, 'password' => $hashedPW), 1, 0 );
    
    
            ### FAILED LOGIN ATTEMPT, increase failed_attempt value
            if ($query2->num_rows () <= 0) {
                $this->messages->add ( sprintf ( lang ( 'error_log_in' ), 'bad_pwd' ), "error" );  
    
                $nb_failed_attempt = $query1->first_row ()->failed_attempt + 1;
                $data = array ('failed_attempt' => $nb_failed_attempt );
    
                $this->db->where('email', $email);
                $this->db->update('user', $data);
                return false;
            }
    
    
            ######## Reset failed login attempt if need be #######
            if ($query2->first_row ()->failed_attempt > 0) {
    
                $nb_failed_attempt = 0;
                $data = array ('failed_attempt' => $nb_failed_attempt );
    
                $this->db->where('email', $email);
                $this->db->update('user', $data);
            }
    
    
            ######### Save info into cookies #########
            $this->session->set_userdata ( array (
                    'id_user' => $query2->first_row ()->id,
                    'email' => $query2->first_row ()->email,
                    'first_name' => $query2->first_row ()->first_name,
                    'last_name' => $query2->first_row ()->last_name,
                    'display_name' => $query2->first_row ()->display_name,
                    'birthdate' => $query2->first_row ()->birthdate,
                    'sex' => $query2->first_row ()->sex,
                    'weight' => $query2->first_row ()->weight,
                    'height' => $query2->first_row ()->height
            ) );
    
    
            return true;
        }
    

    这是我的表&#34;用户&#34;:

    CREATE TABLE IF NOT EXISTS `user` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `email` varchar(150) NOT NULL,
      `password` varchar(255) NOT NULL,
      `failed_attempt` int(3) unsigned DEFAULT 0,
      `salt` varchar(255) NOT NULL,
      `confirm_code` varchar(255),
      `reset_token` varchar(255) NOT NULL,
      `reset_token_expire` datetime DEFAULT NULL,
      `session_id` varchar(255) NOT NULL,
      `first_name` varchar(50) NOT NULL,
      `last_name` varchar(50) NOT NULL,
      `display_name` varchar(50) NOT NULL,
      `birthdate` date NOT NULL,
      `sex` char(1) NOT NULL,
      `last_ip` varchar(50) NOT NULL,
      `last_login` datetime DEFAULT NULL,
      `date_signup` datetime DEFAULT NULL,
      `os` varchar(25) NOT NULL,
      `weight` decimal(5,2) unsigned DEFAULT NULL,
      `height` decimal(5,2) unsigned DEFAULT NULL
    
      PRIMARY KEY (`id`),
      UNIQUE KEY `email` (`email`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ;
    
  • 1 个答案:

    答案 0 :(得分:0)

    您可以在没有Cookie的情况下使用它。有些方法是在表中使用所有IP和计数来检查远程IP,或者只是为username设置计数器而不检查cookie或IP。

    $nb_failed_attempt函数的

    index()是一个全局变量?如果不是 - 你的回答($nb_failed_attempt没有设置每次)。

    <强> UPD

    checkLogin()的开头应该是这样的:

    global $nb_failed_attempt;
    $query1 = $this->db->get_where ( 'user', array ('email' => $email), 1, 0 );
    $nb_failed_attempt = $query1->first_row ()->failed_attempt;
    if(@!$nb_failed_attempt)
        $nb_failed_attempt = 0;
    

    index()的开头应该是这样的:

    global $nb_failed_attempt;
    

    检查错误消息,如果echo $nb_failed_attempt;正常工作,请写信。

    <强> UPD2

    我在大项目中使用会话表的跟随结构:

    CREATE TABLE IF NOT EXISTS `session` (
        `id` bigint AUTO_INCREMENT,
        `login` char(128),
        `ip` char(128),
        `try` smallint,
        `blocktime` datetime,
        `sitesession` char(128),
        `firsttime` datetime,
        `lasttime` datetime,
        PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=1;
    

    它有助于保存有关登录,输入和帮助用户支持的其他信息。

    这张表可能不错,但它对我有用。