一、问题背景:登录接口被大量异常请求攻击
最近维护一个 PHP 后台管理系统,安全人员发现:
登录接口每天出现大量失败请求,部分用户正常登录速度变慢。
监控发现:
/api/login.php
请求量:
平时:
500次/小时
异常:
50000次/小时
用户反馈:
输入正确密码
↓
偶尔提示登录失败
服务器:
PHP进程增加
Redis压力升高
二、问题定位:发现登录接口没有防爆破机制
原始登录代码:
<?php
$username=$_POST['username'];
$password=$_POST['password'];
$user=findUser($username);
if(
password_verify(
$password,
$user['password']
)
){
loginSuccess();
}else{
echo "密码错误";
}
?>
问题:
攻击者可以:
不断尝试密码。
例如:
admin
123456
admin
123457
admin
123458
三、什么是登录暴力破解?
简单理解:
攻击者:
不断尝试:
用户名 + 密码。
流程:
大量请求
↓
登录接口
↓
验证密码
↓
猜测正确密码
如果没有限制:
账号容易被攻击。
四、第一步:限制登录失败次数
设计:
同一个账号:
连续失败:
限制。
例如:
5次失败
↓
锁定10分钟
Redis记录:
$key=
"login_fail:user001";
$count=
$redis->incr($key);
if($count==1){
$redis->expire(
$key,
600
);
}
if($count>5){
exit(
"登录失败次数过多"
);
}
五、第二步:限制IP请求频率
只限制账号:
不够。
攻击者:
可以换账号。
增加:
IP限制。
例如:
一个IP
↓
一分钟最多20次登录
代码:
$key=
"login_ip:".$ip;
$count=
$redis->incr($key);
if($count==1){
$redis->expire(
$key,
60
);
}
if($count>20){
exit(
"请求过于频繁"
);
}
六、第三步:密码不要明文存储
错误:
数据库:
username:
admin
password:
123456
严重风险。
正确:
使用哈希。
PHP:
$passwordHash=
password_hash(
$password,
PASSWORD_DEFAULT
);
数据库保存:
$2y$10$xxxxxxxx
七、登录验证
代码:
if(
password_verify(
$password,
$user['password']
)
){
echo "success";
}
PHP:
自动:
验证哈希。
八、增加验证码机制
适用于:
异常登录。
流程:
失败次数增加
↓
要求验证码
↓
继续登录
例如:
连续失败3次:
出现验证码。
九、图形验证码实现思路
生成随机字符串:
$code=
rand(1000,9999);
保存:
Redis。
$redis->setex(
"captcha:$session",
300,
$code
);
验证:
if(
$input!=$redisCode
){
exit(
"验证码错误"
);
}
十、登录Session安全优化
错误:
登录成功:
直接保存用户ID。
$_SESSION['uid']=$id;
问题:
Session固定攻击。
优化:
登录成功:
重新生成Session。
session_regenerate_id(true);
$_SESSION['uid']=$id;
十一、Token登录设计
移动端:
通常使用Token。
流程:
用户登录
↓
服务器生成Token
↓
返回客户端
↓
后续携带Token
生成:
$token=
bin2hex(
random_bytes(32)
);
保存:
token
user_id
expire_time
十二、Token过期机制
不要永久有效。
例如:
普通登录:
7天
敏感操作:
重新验证
数据库:
CREATE TABLE user_token(
id bigint,
user_id bigint,
token varchar(128),
expire_time datetime
);
十三、异地登录检测
记录:
登录信息。
例如:
{
"user":10086,
"ip":"1.2.3.4",
"device":"iPhone",
"time":"2026-09-29"
}
发现:
异常地区:
提醒用户。
十四、密码修改安全流程
错误:
输入旧密码:
直接修改。
推荐:
流程:
验证旧密码
↓
短信验证
↓
修改密码
↓
清除旧Token
十五、登录日志记录
建议记录:
用户ID
IP
设备
时间
结果
失败原因
例如:
{
"user":10086,
"success":false,
"reason":"password_error"
}
十六、生产环境常见错误
1. 只限制IP
问题:
多人共享IP。
可能误伤。
2. 只限制账号
攻击者:
换账号攻击。
3. 密码使用MD5
错误:
md5($password)
容易被破解。
4. Token永久有效
账号泄露:
长期风险。
十七、上线前检查清单
登录安全
✅ 密码哈希存储
✅ 登录失败限制
✅ IP频率控制
Session/Token
✅ 登录刷新Session
✅ Token过期
✅ 异常登录检测
监控
✅ 登录日志
✅ 异常报警
✅ 风险记录
十八、优化效果
优化前:
大量尝试密码
↓
登录接口压力增加
↓
账号风险提高
优化后:
失败限制
↓
验证码
↓
Token管理
↓
登录稳定安全
总结
登录系统:
不仅是:
用户名 + 密码
生产环境需要考虑:
密码安全
+
防爆破
+
验证码
+
Session安全
+
Token管理
+
登录审计
一个可靠的 PHP 登录系统:
需要同时保证:
安全性、稳定性、可追踪性。
文章标签:
PHP登录系统
PHP安全
登录防爆破
Token认证
Session安全
Redis限流
PHP实战