PHP实现登录错误次数限制
以下代码旨在实现逻辑,状态记录在cookie里不好,攻击者可以清除cookie,为了安全起见应将状态存储到缓存服务器,如redis
<div style="width:100%;height:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;"> <form method="post" action='login.php?login=true'> <div>账号<input type="text" name="username" value="errorAccount"/></div> <div>密码<input type="password" name="password" value="errorAccount"/></div> <button>登录</button> </form> <div> <?php session_start(); $login = empty($_GET['login']) ? '' : trim($_GET['login']); $username = empty($_POST['username']) ? '' : trim($_POST['username']); $password = empty($_POST['password']) ? '' : trim($_POST['password']); if ($login == 'true') { login(); } function login() { global $username; global $password; $limitErrorTimeRange = 1; // 错误累计时间范围,分钟,在这个范围内超过规定次数则锁定一段时间才可登录 $limitErrorCount = 5; // 限制连续登录错误次数,时间范围内连续错误满此次数后锁定一段时间才可登录 $lockTime = 2; // 超限后锁定时长,分钟 $userLoginState = array(); // 初始化用户登录情况全局变量 if (!isset($_SESSION['USER_LOGIN_ERROR_STATE'])) { $_SESSION['USER_LOGIN_ERROR_STATE'] = array( // 用username作为key,存当前用户的状态信息 $username => array( 'prevLoginErrorTime' => 0, // 上次登录错误时间戳(秒) 'errorCount' => 0 // 时间范围内累计错误次数 ) ); } // 得到当前用户的状态信息 $userLoginState = $_SESSION['USER_LOGIN_ERROR_STATE'][$username]; // print_r($userLoginState); // echo '<br/>'; $userPrevLoginErrorTime = $userLoginState['prevLoginErrorTime']; $userErrorCount = $userLoginState['errorCount']; $loginCheck = true; // 若上次错误次数超限则进行解除判定 if ($userErrorCount >= $limitErrorCount) { // 还未到解禁时间,返回限制倒计时提示 // 计算锁定剩余分钟数 $lockSurplusMinutes = ceil((($userPrevLoginErrorTime + $lockTime * 60 - time()) / 60)); if ($lockSurplusMinutes > 0) { echo '你因登录失败次数过多已被锁定,请于' . $lockSurplusMinutes . '分钟后再登录!'; return; // 必须return,防止下面代码修改信息 } // 若已超锁定时长则允许重新登录(重新计数) else { $userErrorCount = 0; // 登录验证 if ($username != 'user' && $password != '123') { $loginCheck = false; echo '1 登录失败<br/>'; } else { echo '1 登录成功<br/>'; } } } // 未超过错误次数限制 else { // 若上次登录已超过累计时间范围则允许登录并重新开启一轮累计 if (time() - $userPrevLoginErrorTime > $limitErrorTimeRange * 60) { $userErrorCount = 0; } // 登录验证 if ($username != 'user' && $password != '123') { $loginCheck = false; echo '登录失败<br/>'; } else { echo '登录成功<br/>'; } } if (!$loginCheck) { // 验证不通过,错误次数+1 $userErrorCount = $userErrorCount + 1; } else { // 验证通过,重置错误次数 $userErrorCount = 0; } echo $userErrorCount . '<br/>'; // 更新用户登录错误信息 $_SESSION['USER_LOGIN_ERROR_STATE'][$username]['prevLoginErrorTime'] = time(); // 秒 $_SESSION['USER_LOGIN_ERROR_STATE'][$username]['errorCount'] = $userErrorCount; // echo '<br/>'; // print_r($_SESSION['USER_LOGIN_ERROR_STATE']); // echo 'ahah<br>'; } ?> </div> </div>
分类:
php
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义