今天无语中查了下阿里云虚拟主机的访问历史, 发现之前使用WordPress被莫名其妙的写入一堆英文的文章的原因查到了, 登录接口被暴力破解导致的, 所有时间比较急, 就写了个简单的POST请求的安全控制的代码, 使用也很简单, 直接在程序入口直接require 这个文件即可, 需要保证这个配置文件定义的限流锁文件保存路径具有写权限
可以看出, 一个登录请求了那么多次, 没办法, 紧急写了个比较粗糙的代码
<?php
// 简单的全局请求安全限制接口
class RequestLimit
{
protected $configFilePath = 'request_limit.lock';
protected $config = [
'GET' => [],// 定义需要限流的类型, 如果不想写配置, 那么就默认以default配置为准
];
protected $default = [
'rate' => '10/60|20/600|30/3600|100/43200|200/86400', // 限制10次/60s, 20次/10分钟, 30次一小时
'try_cont' => 0,
'save_history_count' => 100, // 保留历史条数
'try_history' => [],
];
public function __construct()
{
if (file_exists($this->configFilePath)) {
$this->config = json_decode(file_get_contents($this->configFilePath), true);
}
}
public function handle($method)
{
if (!array_key_exists($method, $this->config)) {
return;
}
if (empty($this->config[$method])) {
$this->config[$method] = $this->default;
}
$this->config[$method]['try_history'] = empty($this->config[$method]['try_history']) ? [] : $this->config[$method]['try_history'];
// 再次请求频率判断, 通过才让继续
foreach (explode('|', $this->config[$method]['rate']) as $item) {
[$x, $y] = explode('/', $item);
if (!empty($this->config[$method]['try_history'][$x - 1]) && $this->config[$method]['try_history'][$x - 1] + $y >= time()) {
header('HTTP/1.1 429 Too Many Requests');
echo '429 Too Many Requests';
exit;
}
}
if (empty($this->config[$method]['save_history_count'])) {
$this->config[$method]['save_history_count'] = 100;
}
array_unshift($this->config[$method]['try_history'], time());
$this->config[$method]['try_history'] = array_slice($this->config[$method]['try_history'], 0, $this->config[$method]['save_history_count']);
$this->config[$method]['try_cont'] = empty($this->config[$method]['try_cont']) ? 1 : $this->config[$method]['try_cont'] + 1;
$this->saveConfig();
}
public function saveConfig()
{
file_put_contents($this->configFilePath, json_encode($this->config, 256));
}
}
$q = new RequestLimit();
$q->handle($_SERVER['REQUEST_METHOD']);