通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志

news2025/5/11 12:20:01

一、TP5.0通过行为(Behavior)拦截爬虫并避免生成 [ error ] NULL 错误日志

1. 创建行为类(拦截爬虫)

在 application/common/behavior 目录下新建BlockBot.php ,用于识别并拦截爬虫请求:

<?php
namespace app\common\behavior;

use think\Response;

class BlockBot
{
    // 爬虫User-Agent特征列表
    protected $botPatterns = [
        '/bot/i', '/spider/i', '/curl/i', '/wget/i', 
        '/python/i', '/scrapy/i', '/crawl/i', '/httpclient/i',
        // 下面是自己添加的爬虫
        '/toutiao/i',
        '/zhanzhang.toutiao.com/i',
        '/dataforseo/i',
        '/dataforseo.com/i',
        '/dataforseo-bot/i',
        '/semrush/i',
        '/www.semrush.com/i',
        '/YisouSpider/i',
    ];

    // 白名单(搜索引擎合法爬虫)
    protected $allowPatterns = [
        '/googlebot/i', '/bingbot/i', '/baiduspider/i', '/Sogou web spider/i'
    ];

    public function run()
    {
        $request = request();
        $userAgent = $request->header('user-agent', '');
        $path = $request->path();

        // 白名单放行
        foreach ($this->allowPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {
                trace("放行{$pattern}爬虫: UA={$userAgent}, Path={$path}", 'info');
                return;
            }
        }

        // 黑名单拦截
        foreach ($this->botPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {

                // 静默记录日志(不触发错误)
                trace("Blocked Bot: UA={$userAgent}, Path={$path}", 'info');

                // 静默拦截(不记录错误日志)
                $this->silentBlock();

            }
        }
    }

    /**
     * 静默拦截逻辑
     */
    private function silentBlock()
    {
        // 返回404页面(或自定义响应)
        $response = Response::create()
            ->code(404)
            ->data('Access Denied')
            ->header(['Content-Type' => 'text/plain']);

        // 终止后续执行
        throw new \think\exception\HttpResponseException($response);
    }

    

}
2. 注册行为到请求事件

在 application/tags.php 中绑定行为到 app_init事件(应用初始化):

return [
    // 应用初始化
    'app_init'     => [
        'app\\common\\behavior\\BlockBot',  //爬虫拦截
    ],
];

3. 自定义异常处理(防止错误日志)
(1) 创建异常处理类

在 application/common/exception 下新建 ExceptionHandler.php,覆盖默认错误处理:

<?php
namespace app\common\exception;

use think\exception\Handle;
use think\exception\RouteNotFoundException;
use think\exception\ValidateException;
use think\Response;

class ExceptionHandler extends Handle
{
    public function render(\Exception $e)
    {
        // 拦截路由不存在错误(常见于爬虫探测)
        if ($e instanceof RouteNotFoundException) {
            return $this->silentResponse(404);
        }

        // 拦截参数验证错误(如分页参数过大)
        if ($e instanceof ValidateException) {
            return $this->silentResponse(400);
        }

        // 其他错误静默记录(可选)
        trace("Silent Error: " . $e->getMessage(), 'error');
        return parent::render($e);
    }

    /**
     * 静默响应(不记录日志)
     */
    private function silentResponse($code)
    {
        return Response::create()
            ->code($code)
            ->data('')
            ->header(['Content-Type' => 'text/plain']);
    }
}
(2) 配置异常处理

在 application/config.php 中指定自定义异常处理器:

// 异常处理配置
'exception_handle' => 'app\common\exception\ExceptionHandler',
4. Nginx层优化(可选)

在服务器配置中拦截部分爬虫并静默处理:

server {
    listen 80;
    server_name yourdomain.com;

    # 拦截爬虫User-Agent并静默处理
    if ($http_user_agent ~* (bot|spider|python|curl|wget)) {
        access_log off;  # 不记录访问日志
        return 444;     # 静默关闭连接
    }

    # 不记录404错误日志
    error_page 404 = /404;
    location = /404 {
        internal;
        access_log off;
    }

    # ThinkPHP伪静态规则
    location / {
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php?s=$1 last;
            break;
        }
    }
}

二、TP5.1或TP6.0通过中间件(middleware)拦截爬虫并避免生成 [ error ] NULL 错误日志

以TP5.1演示:

1. 创建拦截中间件(核心逻辑)

在 application/common/middleware 下新建 BlockBot.php,实现 双重防护:

<?php
namespace app\common\middleware;

use think\Response;

class BlockBot
{
    // 爬虫User-Agent特征列表
    protected $botPatterns = [
        '/bot/i', '/spider/i', '/curl/i', '/wget/i', 
        '/python/i', '/scrapy/i', '/crawl/i', '/httpclient/i'
    ];

    // 白名单(搜索引擎合法爬虫)
    protected $allowPatterns = [
        '/googlebot/i', '/bingbot/i', '/baiduspider/i'
    ];

    public function handle($request, \Closure $next)
    {
        $userAgent = $request->header('user-agent', '');
        $path = $request->pathinfo();

        // 放行白名单爬虫
        foreach ($this->allowPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {
                return $next($request);
            }
        }

        // 拦截黑名单爬虫
        foreach ($this->botPatterns as $pattern) {
            if (preg_match($pattern, $userAgent)) {
                // 静默记录日志(不触发错误)
                trace("Blocked Bot: UA={$userAgent}, Path={$path}", 'info');
                
                // 直接返回404或403,避免后续逻辑执行
                return response('', 404)->header([
                    'Content-Type' => 'text/html; charset=utf-8'
                ]);
            }
        }

        return $next($request);
    }
}
2. 注册中间件(全局生效)

修改 application/config.php 配置,确保中间件在最优先执行:

// 中间件配置
'middleware' => [
    'app\common\middleware\BlockBot', // 添加此行到最前面
    // ...其他中间件
],
3. 防止生成 [ error ] NULL 日志
(1) 自定义错误处理(覆盖ThinkPHP5默认行为)

在 application/config.php 中配置:

// 错误处理配置
'exception_handle'       => 'app\common\exception\ExceptionHandler',

创建 application/common/exception/ExceptionHandler.php:

<?php
namespace app\common\exception;

use think\exception\Handle;
use think\exception\RouteNotFoundException;
use think\exception\ValidateException;
use think\Response;

class ExceptionHandler extends Handle
{
    public function render(\Exception $e)
    {
        // 拦截路由不存在错误(常见于爬虫探测)
        if ($e instanceof RouteNotFoundException) {
            return $this->silentResponse(404);
        }

        // 拦截参数验证错误(如分页过大)
        if ($e instanceof ValidateException) {
            return $this->silentResponse(400);
        }

        // 其他错误按需处理(此处静默记录)
        trace("Silent Error: " . $e->getMessage(), 'error');
        return parent::render($e);
    }

    /**
     * 静默响应(不记录日志)
     */
    private function silentResponse($code)
    {
        return Response::create()
            ->code($code)
            ->data('')
            ->header(['Content-Type' => 'text/plain']);
    }
}
(2) 配置日志过滤

修改 application/config.php 忽略部分错误类型:

// 日志配置
'log' => [
    'type' => 'File',
    'level' => ['error', 'sql'],
    'apart_level' => ['error', 'sql'],
    'ignore_error' => [
        // 忽略路由不存在错误(避免生成 [ error ] NULL 日志)
        'think\exception\RouteNotFoundException',
    ],
],
4. Nginx层优化(双重防护)
server {
    listen 80;
    server_name yourdomain.com;

    # 拦截爬虫User-Agent并静默处理
    if ($http_user_agent ~* (bot|spider|python|curl|wget)) {
        access_log off;  # 不记录访问日志
        return 444;      # 静默关闭连接
    }

    # FastAdmin伪静态规则
    location / {
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php?s=$1 last;
            break;
        }
    }

    # 不记录404错误日志
    error_page 404 = /404.html;
    location = /404.html {
        internal;
        access_log off;
    }
}
注意:经查,网站一直写入[ error ] NULL日志,是因为框架文件thinkphp\library\think\App.php文件代码被恶意篡改

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/3ad9271f561e4ce9ac4d5c9f2867de63.png
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2373109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IBM BAW(原BPM升级版)使用教程第七讲

续前篇&#xff01; 一、团队 在 IBM Business Automation Workflow (BAW) 中&#xff0c;团队&#xff08;Team&#xff09; 是流程管理的关键部分&#xff0c;用于定义参与某个流程的用户、角色、组以及服务等。在团队配置中&#xff0c;有许多重要概念&#xff0c;特别是 …

【论文阅读】Efficient and secure federated learning against backdoor attacks

Efficient and secure federated learning against backdoor attacks -- 高效且安全的可抵御后门攻击的联邦学习 论文来源问题背景TLDR系统及威胁模型实体威胁模型 方法展开服务器初始化本地更新本地压缩高斯噪声与自适应扰动聚合与解压缩总体算法 总结优点缺点 论文来源 名称…

Java中的代理机制

目录 什么叫代理 静态代理 优缺点 优点&#xff1a; 缺点&#xff1a; 动态代理 JDK动态代理 核心类 JDK动态代理的实现 步骤 示例 特点 CGLIB动态代理 代理机制对比 总结 什么叫代理 代理模式是一种比较好理解的设计模式。简单来说就是我们使用代理对象来代替…

Jenkins linux安装

jenkins启动 service jenkins start 重启 service jenkins restart 停止 service jenkins stop jenkins安装 命令切换到自己的下载目录 直接用命令下载 wget http://pkg.jenkins-ci.org/redhat-stable/jenkins-2.190.3-1.1.noarch.rpm 下载直接安装 rpm -ivh jenkins-2.190.3-…

Webug4.0靶场通关笔记-靶场搭建方法(3种方法)

目录 一、虚拟机绿色版本 1. 开启phpstudy 2. 访问靶场 二、Docker版本 1.拉取镜像 2.启动镜像 三、源码安装版本 1. 搭建环境 &#xff08;1&#xff09;安装PHPStudy &#xff08;2&#xff09;WeBug4.0靶场源码 &#xff08;3&#xff09;安装Navicat &#xff…

【Web】LACTF 2025 wp

目录 arclbroth lucky-flag whack-a-mole arclbroth 看到username为admin能拿到flag 但不能重复注册存在的用户 这题是secure-sqlite这个库的问题&#xff0c;底层用的是C&#xff0c;没处理好\0字符截断的问题 &#xff08;在 Node.js 中&#xff0c;由于其字符串表示方式…

【日撸 Java 三百行】综合任务 1

目录 Day 10&#xff1a;综合任务 1 一、题目分析 1. 数据结构 2. 相关函数基本知识 二、模块介绍 1. 初始化与成绩矩阵的构建 2. 创建总成绩数组 3. 寻找成绩极值 三、代码与测试 小结 拓展&#xff1a;关于求极值的相关算法 Day 10&#xff1a;综合任务 1 Task&…

华为私有协议Hybrid

实验top图 理论环节 1. 基本概念 Hybrid接口&#xff1a; 支持同时处理多个VLAN流量&#xff0c;且能针对不同VLAN配置是否携带标签&#xff08;Tagged/Untagged&#xff09;。 核心特性&#xff1a; 灵活控制数据帧的标签处理方式&#xff0c;适用于复杂网络场景。 2. 工作…

数据库实验10

设计性实验 1&#xff0e;实验要求 1.编写函数FsumXXX&#xff0c;1~n&#xff08;参数&#xff09;求和&#xff1b; GO CREATE FUNCTION Fsum065 (n INT) RETURNS INT AS BEGIN DECLARE sum INT 0 WHILE n > 0 BEGIN SET sum sum n SET n n - 1 END RETURN sum END …

jflash下载时出现 Could not read unit serial number! 的解决方法

出现的原因是由于Jlink原厂固件SN码是-1 我用的版本是v6.40 解决方法&#xff1a;添加序列号 1.打开&#xff1a;J-Link commander 之后在命令栏输入&#xff1a;exec setsnxxxxxxxx 2.添加序列号到license&#xff0c;打开J-Link License Manager V6.40 jlink-v640下载软件…

Linux 信号终篇(总结)

前文&#xff1a;本文是对信号从产生到被处理的过程中的概念和原理的总结&#xff0c;如果想了解具体实现&#xff0c;请查看前两篇博客&#xff1a;Linux 信号-CSDN博客、Linux 信号&#xff08;下篇&#xff09;-CSDN博客 一、信号的产生 1.1 信号产生的五种条件 ①键盘组…

LVGL对象(Objects)

文章目录 &#x1f9f1; 一、LVGL 中的对象&#xff08;lv\_obj&#xff09;&#x1f539; lv\_obj\_t 的作用 &#x1f9e9; 二、对象的分类结构&#xff08;类比继承&#xff09;&#x1f9f0; 三、对象的创建与销毁✅ 创建对象示例&#xff1a;创建一个按钮❌ 删除对象 &…

服务器配置错误导致SSL/TLS出现安全漏洞,如何进行排查?

SSL/TLS 安全漏洞排查与修复指南 一、常见配置错误类型‌ 弱加密算法与密钥问题‌ 使用弱密码套件&#xff08;如DES、RC4&#xff09;或密钥长度不足&#xff08;如RSA密钥长度<2048位&#xff09;&#xff0c;导致加密强度不足。 密钥管理不当&#xff08;如私钥未加密存…

路由重发布

路由重发布 实验目标&#xff1a; 掌握路由重发布的配置方法和技巧&#xff1b; 掌握通过路由重发布方式实现网络的连通性&#xff1b; 熟悉route-pt路由器的使用方法&#xff1b; 实验背景&#xff1a;假设学校的某个分区需要配置简单的rip协议路由信息&#xff0c;而主校…

C++修炼:stack和queue

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

【计算机视觉】优化MVSNet可微分代价体以提高深度估计精度的关键技术

优化MVSNet可微分代价体以提高深度估计精度的关键技术 1. 代价体基础理论与分析1.1 标准代价体构建1.2 关键问题诊断 2. 特征表示优化2.1 多尺度特征融合2.2 注意力增强匹配 3. 代价体构建优化3.1 自适应深度假设采样3.2 可微分聚合操作改进 4. 正则化与优化策略4.1 多尺度代价…

软考错题集

一个有向图具有拓扑排序序列&#xff0c;则该图的邻接矩阵必定为&#xff08;&#xff09;矩阵。 A.三角 B.一般 C.对称 D.稀疏矩阵的下三角或上三角部分包含非零元素&#xff0c;而其余部分为零。一般矩阵这个术语太过宽泛&#xff0c;不具体指向任何特定性 质的矩阵。对称矩阵…

T2I-R1:通过语义级与图像 token 级协同链式思维强化图像生成

文章目录 速览摘要1 引言2 相关工作统一生成与理解的 LMM(Unified Generation and Understanding LMM.)用于大型推理模型的强化学习(Reinforcement Learning for Large Reasoning Models.)3 方法3.1 预备知识3.2 语义级与令牌级 CoT语义级 CoT(Semantic-level CoT)令牌级…

Dockers部署oscarfonts/geoserver镜像的Geoserver

Dockers部署oscarfonts/geoserver镜像的Geoserver 说实话&#xff0c;最后发现要选择合适的Geoserver镜像才是关键&#xff0c;所以所以所以…&#x1f437; 推荐oscarfonts/geoserver的镜像&#xff01; 一开始用kartoza/geoserver镜像一直提示内存不足&#xff0c;不过还好…

扩增子分析|微生物生态网络稳定性评估之鲁棒性(Robustness)和易损性(Vulnerability)在R中实现

一、引言 周集中老师团队于2021年在Nature climate change发表的文章&#xff0c;阐述了网络稳定性评估的原理算法&#xff0c;并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标&#xff0c;自此网络稳定性的评估广受大家欢迎。本系列将介绍网络稳定性之鲁棒性…