本文目录导读:

在PHP项目中,要统计“关门防守成功”的次数,通常指的是阻止特定攻击(如SQL注入、XSS、暴力破解等)或限制非法访问的次数,具体实现取决于你的“防守”逻辑是什么。
以下是几种常见场景的统计实现方案:
基于中间件/拦截器的统计(推荐)
如果你使用 Laravel、Symfony 或 ThinkPHP,最好的方式是在全局中间件中统计。
创建日志/统计表
CREATE TABLE defense_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(50) NOT NULL COMMENT '防守类型: sql_injection, brute_force, rate_limit',
ip_address VARCHAR(45) NOT NULL,
count INT DEFAULT 0,
last_attempt_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_type_ip (type, ip_address)
);
中间件逻辑(Laravel示例)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\DB;
class SecurityMiddleware
{
public function handle($request, Closure $next)
{
// --- 防守检测逻辑 ---
$blocked = false;
$type = 'unknown';
// 示例1:检测SQL注入(简单正则)
if (preg_match('/\b(SELECT|UNION|INSERT|DELETE)\b/i', $request->getQueryString() ?? '')) {
$blocked = true;
$type = 'sql_injection';
}
// 示例2:频率限制(防暴力破解)
$ip = $request->ip();
$key = 'login_attempts_' . $ip;
if (cache($key, 0) >= 5) {
$blocked = true;
$type = 'brute_force';
}
// --- 如果触发了防守,则记录 ---
if ($blocked) {
// 原子更新统计(防止并发冲突)
DB::table('defense_logs')
->updateOrInsert(
['type' => $type, 'ip_address' => $ip],
['last_attempt_at' => now()]
);
// 或者使用 Redis 计数器
Redis::incr("defense:{$type}:{$ip}");
// 返回阻断响应
return response('Forbidden', 403);
}
return $next($request);
}
}
基于业务逻辑的统计(登录/API调用)
如果你的“关门”特指限制某用户登录失败或API请求超限:
<?php
class LoginService
{
private $redis;
private $maxAttempts = 5; // 最多尝试次数
public function __construct(\Redis $redis)
{
$this->redis = $redis;
}
public function attemptLogin($username, $password)
{
$key = "login_lock:{$username}";
// 1. 检查是否已被锁住
if ($this->redis->get($key) >= $this->maxAttempts) {
// 统计防守成功次数(自增)
$this->redis->incr("defense_count:login_lock");
return ['success' => false, 'msg' => '账户已被锁定,请稍后再试'];
}
// 2. 模拟验证登陆
if ($this->validateUser($username, $password)) {
$this->redis->del($key);
return ['success' => true];
} else {
// 登录失败,增加尝试次数
$attempts = $this->redis->incr($key);
// 如果达到阈值,记录防守成功
if ($attempts == $this->maxAttempts) {
$this->redis->incr("defense_count:login_lock");
}
return ['success' => false, 'msg' => '账号或密码错误'];
}
}
public function getTotalDefenseCount()
{
return (int)$this->redis->get("defense_count:login_lock") ?: 0;
}
}
通用文件/数据库日志统计(简单项目)
如果不依赖框架,可以用文件记录所有拦截日志,然后用PHP脚本汇总。
写入日志:
<?php
function logDefenseEvent($type, $ip) {
$logFile = __DIR__ . '/defense.log'; // 格式: '2024-01-01 12:00:00|sql_injection|192.168.1.1'
$line = date('Y-m-d H:i:s') . "|{$type}|{$ip}\n";
file_put_contents($logFile, $line, FILE_APPEND);
}
// 在防守触发处调用
if (isset($_GET['id']) && preg_match('/^[0-9]+$/', $_GET['id']) === 0) {
logDefenseEvent('sql_injection', $_SERVER['REMOTE_ADDR']);
// 拦截处理...
die('非法参数');
}
统计输出:
<?php
function getDefenseStats() {
$stats = [];
$lines = file(__DIR__ . '/defense.log', FILE_IGNORE_NEW_LINES);
foreach ($lines as $line) {
$parts = explode('|', $line);
if (count($parts) === 3) {
$type = $parts[1];
$stats[$type] = ($stats[$type] ?? 0) + 1;
}
}
return $stats;
}
// 查看统计
print_r(getDefenseStats());
// 输出: ['sql_injection' => 10, 'brute_force' => 3]
实时仪表板(使用Redis统计)
适合需要实时展示的场景:
<?php
// 防守成功时(Redis计数器)
$redis->incr("defense_total"); // 总次数
$redis->incr("defense_today:" . date('Y-m-d')); // 今日次数
$redis->incr("defense_type:{$type}"); // 按类型统计
// 查询统计
$total = $redis->get("defense_total") ?: 0;
$today = $redis->get("defense_today:" . date('Y-m-d')) ?: 0;
$sqlInjection = $redis->get("defense_type:sql_injection") ?: 0;
重要提示
- 并发问题:使用数据库或Redis的
INCR原子操作,避免SELECT→UPDATE造成的计数丢失。 - 不记录攻击者:如果想记录攻击者IP,可以增加字段。
- 区分类型:建议统计时区分
sql注入、XSS、暴力破解等不同防御类型。
如果你能告诉我具体是哪种“防守”(比如是防火墙、验证码、防刷还是登录限制),我可以给出更精确的代码。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播