本文目录导读:

在PHP中实现IP封禁有多种方法,以下是几种常见的实现方式:
基于文件存储的简单封禁
<?php
class IPBan {
private $banFile = 'banned_ips.txt';
private $cacheFile = 'banned_cache.php';
// 获取用户IP
public function getClientIP() {
$ipAddress = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ipAddress = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ipAddress = trim($ipList[0]);
} else {
$ipAddress = $_SERVER['REMOTE_ADDR'];
}
return $ipAddress;
}
// 检查IP是否被封禁
public function isBanned($ip) {
$bannedIps = $this->getBannedIPs();
return in_array($ip, $bannedIps);
}
// 获取所有被封禁的IP列表
private function getBannedIPs() {
if (file_exists($this->cacheFile)) {
$cached = include($this->cacheFile);
if (isset($cached['expire']) && $cached['expire'] > time()) {
return $cached['ips'];
}
}
$ips = [];
if (file_exists($this->banFile)) {
$lines = file($this->banFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (!empty($line)) {
$ips[] = trim($line);
}
}
}
// 缓存结果,减少文件读取
$this->cacheBannedIPs($ips);
return $ips;
}
// 缓存封禁IP列表
private function cacheBannedIPs($ips) {
$cacheData = [
'ips' => $ips,
'expire' => time() + 300 // 5分钟缓存
];
file_put_contents($this->cacheFile, '<?php return ' . var_export($cacheData, true) . ';');
}
// 添加IP到封禁列表
public function banIP($ip, $reason = '') {
$bannedIps = $this->getBannedIPs();
if (!in_array($ip, $bannedIps)) {
$line = $ip . ($reason ? ' # ' . $reason : '') . PHP_EOL;
file_put_contents($this->banFile, $line, FILE_APPEND);
// 清除缓存
if (file_exists($this->cacheFile)) {
@unlink($this->cacheFile);
}
return true;
}
return false;
}
// 解除IP封禁
public function unbanIP($ip) {
$bannedIps = $this->getBannedIPs();
if (in_array($ip, $bannedIps)) {
$newList = array_diff($bannedIps, [$ip]);
file_put_contents($this->banFile, implode(PHP_EOL, $newList) . PHP_EOL);
// 清除缓存
if (file_exists($this->cacheFile)) {
@unlink($this->cacheFile);
}
return true;
}
return false;
}
}
// 使用示例
$banner = new IPBan();
$clientIP = $banner->getClientIP();
if ($banner->isBanned($clientIP)) {
http_response_code(403);
die('您的IP已被封禁!');
}
// 封禁IP示例
// $banner->banIP('192.168.1.100', '恶意攻击');
// $banner->unbanIP('192.168.1.100');
?>
基于数据库的封禁(推荐)
<?php
class IPBanDB {
private $pdo;
public function __construct($host, $dbname, $user, $pass) {
try {
$this->pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->createTable();
} catch (PDOException $e) {
die('数据库连接失败: ' . $e->getMessage());
}
}
// 创建封禁表
private function createTable() {
$sql = "CREATE TABLE IF NOT EXISTS banned_ips (
id INT AUTO_INCREMENT PRIMARY KEY,
ip VARCHAR(45) NOT NULL UNIQUE,
reason VARCHAR(255),
banned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME DEFAULT NULL,
INDEX idx_ip (ip)
)";
$this->pdo->exec($sql);
}
// 获取用户IP
public function getClientIP() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
return $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]);
}
return $_SERVER['REMOTE_ADDR'];
}
// 检查IP是否被封禁
public function isBanned($ip) {
$sql = "SELECT COUNT(*) FROM banned_ips
WHERE ip = :ip
AND (expires_at IS NULL OR expires_at > NOW())";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([':ip' => $ip]);
return $stmt->fetchColumn() > 0;
}
// 添加封禁
public function banIP($ip, $reason = '', $hours = null) {
$expires = $hours ? date('Y-m-d H:i:s', strtotime("+$hours hours")) : null;
$sql = "INSERT INTO banned_ips (ip, reason, expires_at)
VALUES (:ip, :reason, :expires)
ON DUPLICATE KEY UPDATE reason = :reason2, expires_at = :expires2";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([
':ip' => $ip,
':reason' => $reason,
':expires' => $expires,
':reason2' => $reason,
':expires2' => $expires
]);
}
// 解除封禁
public function unbanIP($ip) {
$sql = "DELETE FROM banned_ips WHERE ip = :ip";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([':ip' => $ip]);
}
// 清除过期记录
public function cleanExpired() {
$sql = "DELETE FROM banned_ips WHERE expires_at IS NOT NULL AND expires_at < NOW()";
return $this->pdo->exec($sql);
}
// 获取封禁信息
public function getBanInfo($ip) {
$sql = "SELECT * FROM banned_ips WHERE ip = :ip";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([':ip' => $ip]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
// 使用示例
$banner = new IPBanDB('localhost', 'mydb', 'user', 'password');
$clientIP = $banner->getClientIP();
if ($banner->isBanned($clientIP)) {
$banInfo = $banner->getBanInfo($clientIP);
http_response_code(403);
echo "您的IP已被封禁!";
if ($banInfo['expires_at']) {
echo " 封禁到期时间: " . $banInfo['expires_at'];
}
if ($banInfo['reason']) {
echo " 原因: " . $banInfo['reason'];
}
die();
}
// 封禁操作
// $banner->banIP('192.168.1.100', '恶意攻击', 24); // 封禁24小时
// $banner->unbanIP('192.168.1.100'); // 解除封禁
// $banner->cleanExpired(); // 清理过期记录
?>
基于Redis的高性能方案
<?php
class IPBanRedis {
private $redis;
private $prefix = 'ip_ban:';
public function __construct($host = 'localhost', $port = 6379, $password = null) {
$this->redis = new Redis();
$this->redis->connect($host, $port);
if ($password) {
$this->redis->auth($password);
}
}
// 获取用户IP
public function getClientIP() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
return $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]);
}
return $_SERVER['REMOTE_ADDR'];
}
// 检查IP是否被封禁
public function isBanned($ip) {
return (bool)$this->redis->exists($this->prefix . $ip);
}
// 添加封禁
public function banIP($ip, $seconds = 3600) {
return $this->redis->set($this->prefix . $ip, time(), $seconds);
}
// 永久封禁
public function banIPForever($ip) {
return $this->redis->set($this->prefix . $ip, -1);
}
// 解除封禁
public function unbanIP($ip) {
return $this->redis->del($this->prefix . $ip);
}
// 获取封禁信息
public function getBanInfo($ip) {
$key = $this->prefix . $ip;
if ($this->redis->exists($key)) {
$value = $this->redis->get($key);
return [
'banned' => true,
'permanent' => $value == -1,
'banned_at' => $value == -1 ? null : date('Y-m-d H:i:s', $value)
];
}
return ['banned' => false];
}
}
// 使用示例
$banner = new IPBanRedis();
$clientIP = $banner->getClientIP();
if ($banner->isBanned($clientIP)) {
http_response_code(403);
die('您的IP已被封禁!');
}
// 封禁操作
// $banner->banIP('192.168.1.100', 3600); // 封禁1小时
// $banner->banIPForever('192.168.1.101'); // 永久封禁
// $banner->unbanIP('192.168.1.100'); // 解除封禁
?>
.htaccess方式(Apache服务器)
# .htaccess <IfModule mod_rewrite.c> RewriteEngine On # 封禁单个IP Deny from 192.168.1.100 # 封禁多个IP Deny from 192.168.1.101 192.168.1.102 192.168.1.103 # 封禁IP段 Deny from 192.168.1.0/24 # 封禁域名 Deny from bad-domain.com </IfModule>
综合使用的最佳实践
<?php
// ipban.php - 综合使用示例
require_once 'IPBanDB.php';
session_start();
class IPBanManager {
private $banManager;
private $maxAttempts = 5;
private $lockoutTime = 900; // 15分钟
public function __construct() {
$config = [
'host' => 'localhost',
'dbname' => 'mydb',
'user' => 'user',
'pass' => 'password'
];
$this->banManager = new IPBanDB(
$config['host'],
$config['dbname'],
$config['user'],
$config['pass']
);
}
public function checkAccess() {
$ip = $this->banManager->getClientIP();
// 检查是否被封禁
if ($this->banManager->isBanned($ip)) {
$this->denyAccess();
}
// 监控登录失败次数
if (isset($_SESSION['login_attempts'][$ip])) {
$attempts = $_SESSION['login_attempts'][$ip];
if ($attempts >= $this->maxAttempts) {
// 自动封禁
$this->banManager->banIP($ip, '多次登录失败', $this->lockoutTime / 3600);
unset($_SESSION['login_attempts'][$ip]);
$this->denyAccess();
}
}
}
public function recordFailedLogin() {
$ip = $this->banManager->getClientIP();
if (!isset($_SESSION['login_attempts'][$ip])) {
$_SESSION['login_attempts'][$ip] = 0;
}
$_SESSION['login_attempts'][$ip]++;
}
private function denyAccess() {
http_response_code(403);
die('访问被拒绝:您的IP已被封禁。');
}
// 管理员功能
public function adminUnban($ip) {
return $this->banManager->unbanIP($ip);
}
public function adminBan($ip, $reason, $hours = null) {
return $this->banManager->banIP($ip, $reason, $hours);
}
}
// 使用
$manager = new IPBanManager();
$manager->checkAccess();
?>
注意事项
- IP获取安全:
HTTP_X_FORWARDED_FOR可能被伪造,建议只信任已知代理的此字段 - IP格式验证:使用
filter_var($ip, FILTER_VALIDATE_IP)验证IP格式 - 性能优化:使用缓存或Redis避免频繁数据库查询
- 批量操作:管理员操作页面建议添加批量封禁/解封功能
- 日志记录:记录所有封禁/解封操作,便于审计
根据你的需求选择合适的方案,对于小型项目,文件存储即可;对于生产环境,建议使用数据库或Redis方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播