本文目录导读:

在PHP项目中实现密码加密和访问校验,推荐使用 bcrypt 或 Argon2 算法(PHP 5.5+ 内置 password_hash 和 password_verify),避免使用 MD5/SHA1 等弱哈希。
以下是完整的安全实现方案:
数据表结构
CREATE TABLE `projects` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `project_name` VARCHAR(255) NOT NULL, `content` TEXT, `access_password` VARCHAR(255) NOT NULL, -- 存储哈希后的密码 `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
密码加密(保存时)
// 用户输入的原始密码
$rawPassword = $_POST['password'];
// 使用 bcrypt 加密(自动生成 salt)
$hashedPassword = password_hash($rawPassword, PASSWORD_BCRYPT, [
'cost' => 12 // 默认10,12更安全
]);
// 保存到数据库
$stmt = $pdo->prepare("INSERT INTO projects (project_name, content, access_password) VALUES (?, ?, ?)");
$stmt->execute([$name, $content, $hashedPassword]);
访问校验(用户输入密码时)
session_start();
// 用户提交的密码
$userInput = $_POST['password'] ?? '';
// 从数据库获取存储的哈希
$stmt = $pdo->prepare("SELECT access_password FROM projects WHERE id = ?");
$stmt->execute([$projectId]);
$row = $stmt->fetch();
$storedHash = $row['access_password'];
// 验证密码
if (password_verify($userInput, $storedHash)) {
$_SESSION['project_access_' . $projectId] = true;
// 允许访问
} else {
// 密码错误
echo "密码错误";
}
中间件校验(保护页面)
function checkProjectAccess($projectId) {
session_start();
// 检查是否有访问权限
if (!isset($_SESSION['project_access_' . $projectId])) {
// 跳转到密码输入页
header('Location: /project/login.php?id=' . $projectId);
exit;
}
}
安全增强建议
1 添加防爆破机制
// 限制错误尝试次数
if (!isset($_SESSION['login_attempts'])) {
$_SESSION['login_attempts'] = 0;
$_SESSION['lockout_time'] = 0;
}
if ($_SESSION['login_attempts'] >= 5) {
if (time() - $_SESSION['lockout_time'] < 900) { // 15分钟锁定
die("登录已锁定,请15分钟后重试");
} else {
$_SESSION['login_attempts'] = 0;
}
}
if (password_verify($userInput, $storedHash)) {
// 成功,重置尝试次数
$_SESSION['login_attempts'] = 0;
} else {
$_SESSION['login_attempts']++;
if ($_SESSION['login_attempts'] >= 5) {
$_SESSION['lockout_time'] = time();
}
}
2 使用 Argon2(推荐,PHP 7.2+)
// 加密
$hashedPassword = password_hash($rawPassword, PASSWORD_ARGON2ID, [
'memory_cost' => 2048, // 内存消耗
'time_cost' => 4, // 时间消耗
'threads' => 2 // 线程数
]);
// 校验(不变)
password_verify($userInput, $storedHash);
3 密码强度要求
function validatePassword($password) {
// 至少8位,包含大小写字母、数字、特殊字符
if (strlen($password) < 8) return false;
if (!preg_match('/[A-Z]/', $password)) return false;
if (!preg_match('/[a-z]/', $password)) return false;
if (!preg_match('/[0-9]/', $password)) return false;
if (!preg_match('/[^a-zA-Z0-9]/', $password)) return false;
return true;
}
完整示例页面
密码输入页面 (project_login.php):
<?php
session_start();
$projectId = $_GET['id'] ?? 0;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$userInput = $_POST['password'] ?? '';
// 从数据库获取哈希并校验...
if (password_verify($userInput, $storedHash)) {
$_SESSION['project_access_' . $projectId] = true;
header('Location: /project/view.php?id=' . $projectId);
exit;
} else {
$error = "密码错误";
}
}
?>
<form method="POST">
<input type="password" name="password" required>
<button type="submit">访问项目</button>
<?php if (isset($error)): ?>
<p style="color:red"><?= $error ?></p>
<?php endif; ?>
</form>
项目查看页面 (project_view.php):
<?php require_once 'auth_check.php'; // 包含校验函数 $projectId = $_GET['id'] ?? 0; checkProjectAccess($projectId); // 显示项目内容...
- 使用
password_hash()加密,不要自己实现哈希 - 使用
password_verify()校验,避免时序攻击 - 不要存储明文密码,永远不要
- 添加防爆破措施,限制错误尝试
- 使用 HTTPS 防止中间人攻击
- 定期更换密码,建议90天
这种方案安全可靠,能有效防止密码泄露和暴力破解。