本文目录导读:

我来详细说明PHP中实现黑名单鉴权的几种方法:
基于IP的黑名单鉴权
简单IP黑名单
<?php
class IPBlacklist {
private $blacklist = [
'192.168.1.100',
'10.0.0.50',
'172.16.0.1'
];
public function checkIP() {
$userIP = $_SERVER['REMOTE_ADDR'];
if (in_array($userIP, $this->blacklist)) {
$this->denyAccess("IP被禁止访问");
return false;
}
return true;
}
private function denyAccess($message) {
http_response_code(403);
echo json_encode(['error' => $message]);
exit;
}
}
IP范围黑名单(支持CIDR)
<?php
class IPBlacklistManager {
private $blacklist = [
'192.168.1.0/24', // 整个C段
'10.0.0.0/8', // A类地址段
'172.16.0.0/12' // B类地址段
];
public function isIpInRange($ip, $cidr) {
list($subnet, $bits) = explode('/', $cidr);
$ip = ip2long($ip);
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
return ($ip & $mask) == ($subnet & $mask);
}
public function checkAccess() {
$userIP = $_SERVER['REMOTE_ADDR'];
foreach ($this->blacklist as $cidr) {
if ($this->isIpInRange($userIP, $cidr)) {
header('HTTP/1.0 403 Forbidden');
exit('访问被拒绝');
}
}
}
}
用户/账号黑名单
<?php
class UserBlacklist {
private $db; // 数据库连接
public function checkUser($userId) {
// 从数据库获取黑名单
$blacklist = $this->getBlacklistFromDB();
if (in_array($userId, $blacklist)) {
$this->logBlacklistAccess($userId);
throw new Exception("用户已被禁止访问");
}
}
private function getBlacklistFromDB() {
// 示例:从数据库查询黑名单
$stmt = $this->db->query("SELECT user_id FROM blacklist WHERE status = 1");
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
public function addToBlacklist($userId, $reason) {
$stmt = $this->db->prepare(
"INSERT INTO blacklist (user_id, reason, created_at)
VALUES (?, ?, NOW())"
);
return $stmt->execute([$userId, $reason]);
}
}
请求频率黑名单(防爬虫)
<?php
class RateLimitBlacklist {
private $redis;
private $maxRequests = 100; // 每分钟最大请求数
private $banDuration = 3600; // 封禁时长(秒)
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function checkRateLimit() {
$ip = $_SERVER['REMOTE_ADDR'];
$key = "rate_limit:{$ip}";
// 检查是否在黑名单中
if ($this->redis->get("blacklist:{$ip}")) {
$this->denyAccess("请求过于频繁,已被临时封禁");
}
// 增加请求计数
$count = $this->redis->incr($key);
if ($count === 1) {
$this->redis->expire($key, 60); // 60秒过期
}
// 超过限制,加入黑名单
if ($count > $this->maxRequests) {
$this->redis->setex("blacklist:{$ip}", $this->banDuration, 1);
$this->denyAccess("触发频率限制");
}
}
}
基于规则的黑名单
<?php
class RuleBasedBlacklist {
private $rules = [
'user_agent' => [
'badbot',
'scraper',
'curl/7.0'
],
'referer' => [
'spam-site.com',
'malware-site.net'
],
'headers' => [
'X-Forwarded-For' => ['malicious-ip']
]
];
public function checkAllRules() {
// 检查User-Agent
if ($this->matchUserAgent()) {
$this->blockRequest();
}
// 检查Referer
if ($this->matchReferer()) {
$this->blockRequest();
}
// 检查自定义头
if ($this->matchHeaders()) {
$this->blockRequest();
}
}
private function matchUserAgent() {
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
foreach ($this->rules['user_agent'] as $pattern) {
if (stripos($ua, $pattern) !== false) {
return true;
}
}
return false;
}
}
完整的黑名单中间件
<?php
class BlacklistMiddleware {
private $config;
public function __construct() {
$this->config = require 'blacklist_config.php';
}
public function handle($request) {
// 1. IP检查
if (!$this->checkIP($request->ip)) {
return $this->deny();
}
// 2. User-Agent检查
if (!$this->checkUserAgent($request->userAgent)) {
return $this->deny();
}
// 3. 请求频率检查
if (!$this->checkRateLimit($request->ip)) {
return $this->deny();
}
// 4. Token/API Key检查
if (!$this->checkToken($request->bearerToken)) {
return $this->deny();
}
return true;
}
private function deny() {
http_response_code(403);
header('Content-Type: application/json');
echo json_encode([
'status' => false,
'message' => 'Access Denied',
'code' => 403
]);
exit;
}
}
数据库表结构
-- IP黑名单表
CREATE TABLE ip_blacklist (
id INT PRIMARY KEY AUTO_INCREMENT,
ip_address VARCHAR(45) NOT NULL,
cidr VARCHAR(45),
reason TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NULL,
INDEX idx_ip (ip_address)
);
-- 用户黑名单表
CREATE TABLE user_blacklist (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
reason TEXT,
blacklist_type ENUM('temporary', 'permanent') DEFAULT 'temporary',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NULL,
INDEX idx_user (user_id)
);
性能优化建议
<?php
// 1. 使用缓存
class CachedBlacklist {
private $cache;
private $cacheTTL = 300; // 5分钟
public function isBlacklisted($key) {
$cacheKey = "blacklist_check:{$key}";
// 从缓存获取
if ($this->cache->has($cacheKey)) {
return $this->cache->get($cacheKey);
}
// 实际检查逻辑
$result = $this->checkBlacklist($key);
// 写入缓存
$this->cache->set($cacheKey, $result, $this->cacheTTL);
return $result;
}
}
// 2. 使用布隆过滤器(大规模黑名单)
class BloomFilterBlacklist {
private $redis;
private $bloomKey = 'ip_blacklist_bloom';
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function isBlacklisted($ip) {
// Redis 4.0+ 支持布隆过滤器
return $this->redis->rawCommand('BF.EXISTS', $this->bloomKey, $ip);
}
public function addToBlacklist($ip) {
return $this->redis->rawCommand('BF.ADD', $this->bloomKey, $ip);
}
}
实际使用示例
<?php // 启动黑名单检查 $blacklist = new BlacklistMiddleware(); $blacklist->handle($_SERVER); // 继续执行正常逻辑 echo "欢迎访问";
注意事项:
- 定期更新黑名单数据
- 记录所有黑名单拦截日志
- 提供白名单例外机制
- 注意性能影响,必要时使用缓存
- 考虑使用第三方服务(如Cloudflare)
根据具体需求选择合适的黑名单鉴权方式,可以是单一方式或组合使用。