0

我想要做的是弄清楚我应该在哪里放置一段代码,它需要检查是否尝试了最大登录尝试,然后它会检查 10 分钟是否已经过去,但这样用户可以尝试再次登录。不知道应该如何添加这个逻辑。

function submit()
{
    // Sets validation rules for the login form
    $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
    $this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean');
    $this->form_validation->set_rules('remember', 'Remember me', 'integer');

    // Checks to see if login form was submitted properly
    if ($this->form_validation->run() === false)
    {
        $outputArray = array('error' => 'yes', 'message' => 'There was a problem submitting the form! Please refresh the window and try again!');  
    }
    else
    {
        if (is_null($userData = $this->usersmodel->getUserByUsername($this->input->post('username'))))
        {
            // Username was not found in the database
            $outputArray = array('error' => 'yes', 'message' => 'Incorrect username and password combination!');  
        }
        else
        {
            // Checks to see if user has exceeded max login attempts
            if ($this->auth->isMaxLoginAttemptsExceeded($userData->userID))
            {

                // Max was exceeded and sends email to account holder
                $outputArray = array('error' => 'yes', 'message' => 'Your account is currently locked, we appologize for the inconvienence. You must wait 10 minutes before you can login again! An email was sent to the owner of this account!');  
                $userData = array('userID' => $userData->userID, 'firstName' => $userData->firstName, 'lastName' => $userData->lastName, 'email' => $userData->email, 'username' => $userData->username);
                $this->auth->sendEmail($this->config->item('defaultTemplate'), 'maxlogins', 'KOW Manager Account Locked', $userData);  
            }
            else
            {
                // Matches user's status for validity
                switch($userData->usersStatusesID)
                {
                    // Registered not validated
                    case 1:
                        $outputArray = array('error' => 'yes', 'message' => 'Sorry you must verify your account before logging in!');  
                        break;
                    // Account suspended
                    case 3:  
                        $outputArray = array('error' => 'yes', 'message' => 'Your account has been suspended!');  
                        break;
                    // Account Banned
                    case 4:
                        $outputArray = array('error' => 'yes', 'message' => 'Your account is currently banned!');  
                        break;
                    // Account Deleted
                    case 5:  
                        $outputArray = array('error' => 'yes', 'message' => 'Your account has been deleted!');  
                        break;
                    // Registered and validated
                    default:
                        // Checks to see if login was successful
                        if ($this->auth->login($this->input->post('username'), $this->input->post('password'), $this->input->post('remember')))
                        {
                            // Login was successful
                            $outputArray = array('success' => 'Yes', 'message' => 'Sending to control panel!');    
                        }
                        else
                        {
                            // Login failed
                            $outputArray = array('error' => 'yes', 'message' => 'Incorrect username and password combination!');  
                        } 
                }
            }

        }
    }
    echo json_encode($outputArray);      
}

/**
* Check if login attempts exceeded max login attempts
*
* @param       integer
* @return      bool
*/
function isMaxLoginAttemptsExceeded($userID)
{
    $this->ci->load->model('users/usersmodel');
    $loginAttempts = $this->ci->usersmodel->getLoginAttemptsNum($this->ci->input->ip_address(), $userID);
    if ($loginAttempts >= 5)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
 * Get number of attempts to login occured from given IP-address or username
 *
 * @param   string
 * @param   string
 * @return  integer
 */
function getLoginAttemptsNum($ipAddress, $userID)
{
    $this->db->where('ipAddress', $ipAddress);
    $this->db->or_where('userID', $userID);
    $query = $this->db->get($this->usersLoginsAttempts);
    if ($query->num_rows > 0)
    {
        return $query->num_rows;          
    }
    else
    {
        return 0;
    }        
}

Fields: id, userID, ipAddress, datetime

每次用户进行不正确的登录时,它都会在字段中添加另一行,该字段按 ipAddress 或 userID 中的每 5 个来存储它。所以它需要查看最后一个日期时间,因为它只存储最后 5 个。

4

1 回答 1

1

您的第一选择是是否在以下情况下锁定用户:

  • 已从计算机进行了 5 次无效尝试,任何用户名(更有可能抓住黑客)
  • 使用相同的有效用户名进行了 5 次无效尝试(更有可能捕获知道用户名但不知道密码的用户)。

您设置的方法是其中的第二种(根据您的功能判断 isMaxLoginAttemptsExceeded($userData->userID)) )

所以,基于此:

阶段1:

向用户的数据库添加 3 个字段:“invalid_login_count”、“last_invalid”attempt”和“locked_out_until”

阶段1:

在“// 登录失败”这一行周围,您需要记录进行了无效尝试的事实。增加“invalid_login_count”并存储在数据库中,将“last_invalid_attempt”设置为现在。如果“invalid_login_count”= 5,则还将“locked_out_until”更新为时间 + 5 分钟。

第 2 阶段:

在“//登录成功”这一行周围清除“invalid_login_count”、“last_invalid_attempt”和“locked_out_until”的值(即重置)

第三阶段:

如果“last_invalid_attempt”有一个值,并且是在不到 5 分钟之前,则清除“locked_out_until”、“last_invalid_attempt”和“invalid_login_count”中的值。获取用户详细信息后立即执行此操作,无论是无效还是现在。

第 4 阶段:

您的 $this->auth->isMaxLoginAttemptsExceeded($userData->userID) 函数应该查看“locked_out_until”值,如果 > now,则它们被锁定。

注意:这意味着用户不能输入 5 次无效尝试,每次间隔小于 5 分钟。这并不完全符合您的要求(5 分钟内尝试 5 次),但是存储所有最新尝试的时间并且仅包括最后 5 分钟的值的逻辑有点困难 - 所以我保持简单。


请注意,我实际上建议按 IP 地址锁定,这是稍微不同的逻辑,因为您需要有一个特定的表来计算尝试次数并按 IP 锁定,并且您还需要在两个地方进行更新(如果未找到用户名,或者如果密码无效),如果 IP 被锁定,您应该在检查用户名是否有效之前将用户退出。否则,这是相同的逻辑。

于 2012-05-31T12:13:57.323 回答