安全的登录系统
php
<?php
session_start();
// 1. 防暴力破解
function check_login_attempts($username) {
$attempts = $_SESSION['login_attempts'][$username] ?? 0;
$last_attempt = $_SESSION['last_attempt'][$username] ?? 0;
// 5次失败后锁定30分钟
if($attempts >= 5 && (time() - $last_attempt) < 1800) {
return false;
}
return true;
}
// 2. CSRF Token验证
function verify_csrf_token($token) {
return isset($_SESSION['csrf_token']) &&
hash_equals($_SESSION['csrf_token'], $token);
}
// 3. 安全的密码验证
function secure_login($username, $password, $csrf_token) {
// CSRF验证
if(!verify_csrf_token($csrf_token)) {
return ['success' => false, 'message' => 'CSRF验证失败'];
}
// 登录次数检查
if(!check_login_attempts($username)) {
return ['success' => false, 'message' => '账户已锁定'];
}
// 输入验证
if(!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
return ['success' => false, 'message' => '用户名格式错误'];
}
// 预编译查询
global $conn;
$stmt = $conn->prepare("SELECT id, password FROM users WHERE username = ? LIMIT 1");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if($row = $result->fetch_assoc()) {
// 使用password_verify验证密码
if(password_verify($password, $row['password'])) {
// 登录成功,清除失败记录
unset($_SESSION['login_attempts'][$username]);
$_SESSION['user_id'] = $row['id'];
return ['success' => true];
}
}
// 登录失败,记录次数
$_SESSION['login_attempts'][$username] =
($_SESSION['login_attempts'][$username] ?? 0) + 1;
$_SESSION['last_attempt'][$username] = time();
return ['success' => false, 'message' => '用户名或密码错误'];
}
// 4. 处理登录请求
if($_SERVER['REQUEST_METHOD'] === 'POST') {
$result = secure_login(
$_POST['username'] ?? '',
$_POST['password'] ?? '',
$_POST['csrf_token'] ?? ''
);
if($result['success']) {
header('Location: dashboard.php');
exit;
} else {
$error = htmlspecialchars($result['message']);
}
}
// 5. 生成新的CSRF Token
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>
<!DOCTYPE html>
<html>
<head>
<title>安全登录</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
</head>
<body>
<?php if(isset($error)): ?>
<div style="color: red;"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<label>用户名:</label>
<input type="text" name="username" required pattern="[a-zA-Z0-9_]{3,20}">
<br>
<label>密码:</label>
<input type="password" name="password" required>
<br>
<button type="submit">登录</button>
</form>
</body>
</html>
安全的命令执行
php
<?php
// 不安全的方式
// $output = shell_exec("ping " . $_GET['ip']);
// 安全方式1:白名单验证
function safe_ping($ip) {
// 验证IP格式
if(!filter_var($ip, FILTER_VALIDATE_IP)) {
return "无效的IP地址";
}
// 使用escapeshellarg()转义参数
$safe_ip = escapeshellarg($ip);
// 限制命令和参数
if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$cmd = "ping -n 4 {$safe_ip}";
} else {
$cmd = "ping -c 4 {$safe_ip}";
}
// 执行并返回
return shell_exec($cmd);
}
// 安全方式2:使用专用函数(更好)
function safe_ping_v2($ip) {
if(!filter_var($ip, FILTER_VALIDATE_IP)) {
return "无效的IP地址";
}
// 使用PHP的socket函数代替系统命令
$errno = 0;
$errstr = '';
$socket = @fsockopen($ip, 80, $errno, $errstr, 5);
if($socket) {
fclose($socket);
return "主机 {$ip} 可达";
} else {
return "主机 {$ip} 不可达";
}
}
?>
安全的XSS防护
php
<?php
// XSS防护函数库
class XSSProtection {
// HTML上下文输出
public static function escapeHTML($string) {
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
// JavaScript上下文输出
public static function escapeJS($string) {
return json_encode($string, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
}
// URL上下文输出
public static function escapeURL($string) {
return rawurlencode($string);
}
// 富文本过滤(允许部分HTML)
public static function filterRichText($html) {
// 使用HTMLPurifier库
require_once 'HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
return $purifier->purify($html);
}
}
// 使用示例
$username = $_GET['name'] ?? '';
// HTML上下文
echo "<div>欢迎 " . XSSProtection::escapeHTML($username) . "</div>";
// JavaScript上下文
echo "<script>var username = " . XSSProtection::escapeJS($username) . ";</script>";
// URL上下文
echo "<a href='profile.php?user=" . XSSProtection::escapeURL($username) . "'>个人资料</a>";
?>
安全的CSRF防护
php
<?php
// CSRF防护类
class CSRFProtection {
// 生成Token
public static function generateToken() {
if(!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
// 验证Token
public static function verifyToken($token) {
if(!isset($_SESSION['csrf_token'])) {
return false;
}
return hash_equals($_SESSION['csrf_token'], $token);
}
// 生成表单字段
public static function tokenField() {
$token = self::generateToken();
return '<input type="hidden" name="csrf_token" value="' . $token . '">';
}
// 检查并验证(中间件模式)
public static function protect() {
if($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['csrf_token'] ?? '';
if(!self::verifyToken($token)) {
http_response_code(403);
die('CSRF Token验证失败');
}
}
}
}
// 使用示例
session_start();
CSRFProtection::protect(); // 在所有POST处理前调用
// 表单中使用
?>
<form method="POST">
<?php echo CSRFProtection::tokenField(); ?>
<input type="text" name="data">
<button type="submit">提交</button>
</form>