首页 > 解决方案 > 在 PHP 中 6 次登录尝试失败后如何阻止用户 40 分钟

问题描述

我正在尝试创建一个用于登录限制的脚本。如果他/她无法登录 6 次,我想阻止用户登录 40 分钟。我创建了一个login_attempts包含列的表: ip_address, username, created_at。当用户提交登录表单时,我在数据库中添加用户的 IP 地址和用户名。然后在登录页面上,如果用户没有超过最大登录尝试次数,我将显示登录表单。如果用户超过了登录尝试的最大次数,我会显示错误并删除登录页面上超过 40 分钟的日志。但在 6 次失败的登录尝试后,我仍然看到登录表单。

有什么建议么?

<?php

// Login Page

delete_records_older_than(40, 'created_at', 'login_attempts');

if (has_exceeded_max_login_attempts($_SERVER['REMOTE_ADDR'], 6)) {
  // please try again after 40 minutes
} else {
  // show the login form
}

表单处理脚本

<?php

// ON Form submit

if (login) {
  // mark user as logged in
} else {
  add_login_attempt_in_db($username, $_SERVER['REMOTE_ADDR']);
}

这是我的功能:

function add_login_attempt_in_db($username, $address)
{
  global $db;
  $sql = 'INSERT INTO login_attempts(username, ip_address, created_at) VALUES (?, ?, CURRENT_TIMESTAMP)';
  $stmt = mysqli_stmt_init($db);
  mysqli_stmt_prepare($stmt, $sql);

  mysqli_stmt_bind_param($stmt, 'ss', $username, $address);
  $result = mysqli_stmt_execute($stmt);
  mysqli_stmt_close($stmt);
  if (!$result) {
    return false;
  } else {
    return true;
  }
}

function delete_records_older_than($minutes, $date_column, $table)
{
  global $db;
  $sql = 'DELETE FROM ' . $table . ' WHERE ' . $date_column . ' < (NOW() - INTERVAL ' . $minutes . ' MINUTE)';
  $stmt = mysqli_stmt_init($db);
  mysqli_stmt_prepare($stmt, $sql);
  mysqli_stmt_execute($stmt);
}

function has_exceeded_max_login_attempts($ip_address, $limit)
{
  global $db;
  $sql = 'SELECT COUNT(id) AS attempts FROM login_attempts WHERE ip_address LIKE ? AND created_at > (now() - interval 40 minute)';
  $stmt = mysqli_stmt_init($db);
  mysqli_stmt_prepare($stmt, $sql);
  mysqli_stmt_bind_param($stmt, 's', $ip_address);
  mysqli_stmt_execute($stmt);
  $result = mysqli_stmt_get_result($stmt);
  mysqli_stmt_close($stmt);
  // fetch result
  $result = mysqli_fetch_assoc($result);
  return $result['attempts'] >= $limit;
}

标签: phpmysql

解决方案


推荐阅读