题目
设计一个安全的用户登录系统
信息
- 类型:问答
- 难度:⭐⭐
考点
会话管理,密码安全,SQL注入防护
快速回答
实现安全登录系统的核心要点:
- 使用
password_hash()和password_verify()处理密码 - 预处理语句防止SQL注入
- 会话固定/劫持防护:
session_regenerate_id()和HTTPS - 登录失败限制和日志记录
- 设置合理的会话过期时间
1. 核心安全要求
安全的登录系统需要满足:
- 密码不可逆存储(哈希+盐值)
- 防止数据库注入攻击
- 会话标识符安全传输和存储
- 暴力破解防护机制
- 敏感操作二次验证
2. 代码实现示例
<?php
// 登录处理逻辑
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 1. 数据库查询(使用预处理)
$stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
// 2. 密码验证
if ($user && password_verify($password, $user['password'])) {
// 3. 会话安全设置
session_regenerate_id(true); // 防止会话固定
$_SESSION['user_id'] = $user['id'];
$_SESSION['login_time'] = time();
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
// 4. 跳转到安全区域
header('Location: /dashboard.php');
exit;
} else {
// 记录失败尝试
log_failed_attempt($_SERVER['REMOTE_ADDR']);
$error = "Invalid credentials";
}
}
// 密码存储示例(注册时)
$hashedPassword = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
?>3. 关键安全措施详解
密码安全
- 使用
password_hash()(默认使用BCRYPT算法)和password_verify() - 成本因子(cost)建议12-14,平衡安全与性能
- 绝对禁止使用MD5/SHA1等弱哈希算法
SQL注入防护
- 使用PDO或MySQLi预处理语句
- 示例中
?占位符确保输入数据与SQL指令分离 - 避免直接拼接SQL语句:
"SELECT ... WHERE user='$username'"
会话安全
session_regenerate_id(true):登录成功后更新会话ID,防止会话固定攻击- 绑定用户特征(User-Agent+IP):每次请求验证会话特征一致性
- 设置会话过期:
ini_set('session.gc_maxlifetime', 1800); // 30分钟
其他防护
- 登录失败限制:5次失败后锁定账户或要求验证码
- HTTPS强制:防止中间人攻击,设置
session.cookie_secure=On - CSRF防护:敏感操作使用Token验证
4. 常见错误
- ❌ 使用
md5($password)存储密码 - ❌ 未更新会话ID导致会话固定漏洞
- ❌ 未设置会话过期时间,导致长期有效会话
- ❌ 未处理登录失败限制,允许暴力破解
- ❌ 在错误消息中泄露敏感信息(如"用户名不存在")
5. 扩展知识
- 双因素认证(2FA):集成TOTP(基于时间的一次性密码)
- 密码策略:强制最小长度(12+)、特殊字符要求
- 持续监控:日志分析异常登录行为(异地登录、非常规时间)
- 现代替代方案:JWT认证、OAuth2.0集成