【问题标题】:CakePHP error log - can I exclude 404 errors?CakePHP 错误日志 - 我可以排除 404 错误吗?
【发布时间】:2014-03-24 10:58:57
【问题描述】:

我的 CakePHP 应用程序的错误日志充满了 404 错误。我可以将这些MissingControllerExceptions 排除在错误日志中吗?使用 Cake 2.3。

【问题讨论】:

  • 忽略错误几乎是鸵鸟方法。他们被抛出是有原因的。显然,您的应用程序中的链接已损坏,并且您的用户单击了它们。可能是您想要解决的问题。
  • @Oldskool - 错误主要针对存在于网站先前版本但不再存在的资源。在这些情况下,没有相关的新位置可以重定向,并且重定向到主页会令人困惑,所以 404 并不是我想知道的真正错误。
  • 除非您没有使用正确的 Helpers,否则丢失的资源不应触发 MissingControllerException。无论哪种方式,要捕获任何“旧” URL,您都应该使用 Routes 将它们重写到新位置(或自定义 404 页面,通知用户他们正在使用过时的链接),而不是抑制异常。
  • 我说的是在站点成为 CakePHP 应用程序之前就存在的旧 URL,尤其是图像文件。例如,/images/sm/image.jpg。此图像没有“新位置”。如果我可以阻止这样的 URL 触发 MissingControllerException,那么我会非常高兴(尽管我不会为这些文件中的每一个都设置一个重定向,因为有数百个!)
  • 我明白这一点,但您不必为每个单独的图像创建规则。例如,您可以只重写所有旧的图像链接,并且仍然保持正常工作的异常系统。例如,在您的app/webroot/.htaccess 中,在Cake “整体”重写之前,只需添加:RewriteRule ^images/.* - [L,R=404]。这会立即从 Apache 抛出 404(所以 Cake 没有用它做任何事情)。

标签: cakephp cakephp-2.0


【解决方案1】:

2.4 以上的版本(如 null 所述)为此目的具有未记录的功能。

只需修改您的异常配置:

Configure::write('Exception', array(
    'handler' => 'ErrorHandler::handleException',
    'renderer' => 'ExceptionRenderer',
    'log' => true,
    'skipLog'=>array(
        'MissingControllerException'
    )
));

skipLog 采用要从日志中排除的异常类的名称。

【讨论】:

  • 2.4 migration guide 中有提及。 New configuration option skipLog has been added, to allow skipping certain Exception types to be logged. Configure::write('Exception.skipLog', array('NotFoundException', 'ForbiddenException')); will avoid these exceptions and the ones extending them to be be logged when 'Exception.log' config is true
  • 谢谢,这对我有帮助!
  • +1:对于繁忙的站点,此解决方案可能更好(不是泛化),因为错误日志需要文件写入。这不适合资源有限的服务器。
【解决方案2】:

仅仅重定向或删除这些 URL 并不能解决问题。

一个繁忙的网站每天都会受到数百个“随机”404 的攻击,大多数来自远东国家/地区检查漏洞或 URL,例如“/wp-admin”。

完全没有必要用完整的堆栈跟踪记录这些

解决方案

您可以覆盖 CakePHP 中的默认错误处理程序,并改为登录到 app/tmp/logs/404.log

在您的app/Config/core.php 文件中,定义您要处理异常的类:

Configure::write('Error', array(
    'handler' => 'MyCustomErrorHandler::handleError',
    'level' => E_ALL & ~E_DEPRECATED,
    'trace' => true
));

app/Lib/Error 中创建类,并在您的app/Config/bootstrap.php 文件中使用App::uses

App::uses('MyCustomErrorHandler', 'Lib/Error');

制作原始 ErrorHandler 类的精确副本,只需更改类名,并在 handleException 方法中的某处检查抛出了哪个异常,并在其他地方记录。它看起来有点像这样;

App::uses('ErrorHandler', 'Error');

class MyCustomErrorHandler {

    public static function handleException(Exception $exception) {

         // some code...

         if (in_array(get_class($exception), array('MissingControllerException', 'MissingActionException', 'PrivateActionException', 'NotFoundException'))) {
             $log = '404';
             $message = sprintf("[%s]", get_class($exception));
         }

         // more code...
    }

}

【讨论】:

  • 终于开始实现这个并且效果很好,除了我必须更改异常的配置,而不是错误。我也没有复制整个文件,而是扩展了它。
【解决方案3】:

基于 robmcvey 的解决方案,这是我必须为 CakePHP 2.6 做的事情。

配置

app/Config/core.php更新异常配置:

Configure::write('Exception', array(
    'handler' => 'AppErrorHandler::handleException',
    'renderer' => 'ExceptionRenderer',
    'log' => true
));

app/Config/bootstrap.php 中添加一个 CakeLog 配置:

CakeLog::config('not_found', array(
    'engine' => 'FileLog',
    'types' => array('404'),
    'file' => '404',
));

404type 是日志级别,它将监听写入日志的任何内容,例如CakeLog::write('404', 'That was not found.');

扩展错误处理程序

创建文件app/Lib/Error/AppErrorHandler.php。这里我们将扩展Cake的ErrorHandler,覆盖三个方法; handleException()_getMessage()_log()

<?php
class AppErrorHandler extends ErrorHandler {

/**
 * List of Cake Exception classes to record to specified log level.
 *
 * @var array
 */
    protected static $_exceptionClasses = array(
        'MissingControllerException' => '404',
        'MissingActionException' => '404',
        'PrivateActionException' => '404',
        'NotFoundException' => '404'
    );

    public static function handleException(Exception $exception) {
        $config = Configure::read('Exception');
        self::_log($exception, $config);

        $renderer = isset($config['renderer']) ? $config['renderer'] : 'ExceptionRenderer';
        if ($renderer !== 'ExceptionRenderer') {
            list($plugin, $renderer) = pluginSplit($renderer, true);
            App::uses($renderer, $plugin . 'Error');
        }
        try {
            $error = new $renderer($exception);
            $error->render();
        } catch (Exception $e) {
            set_error_handler(Configure::read('Error.handler')); // Should be using configured ErrorHandler
            Configure::write('Error.trace', false); // trace is useless here since it's internal
            $message = sprintf("[%s] %s\n%s", // Keeping same message format
                get_class($e),
                $e->getMessage(),
                $e->getTraceAsString()
            );

            self::$_bailExceptionRendering = true;
            trigger_error($message, E_USER_ERROR);
        }
    }

/**
 * Generates a formatted error message
 *
 * @param Exception $exception Exception instance
 * @return string Formatted message
 */
    protected static function _getMessage($exception) {
        $message = '';
        if (php_sapi_name() !== 'cli') {
            $request = Router::getRequest();
            if ($request) {
                $message .= $request->here() . " Not Found";
            }
        }
        $message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n";
        return $message;
    }

/**
 * Handles exception logging
 *
 * @param Exception $exception The exception to render.
 * @param array $config An array of configuration for logging.
 * @return bool
 */
    protected static function _log(Exception $exception, $config) {
        if (!empty(self::$_exceptionClasses)) {
            foreach ((array)self::$_exceptionClasses as $class => $level) {
                if ($exception instanceof $class) {
                    return CakeLog::write($level, self::_getMessage($exception));
                }
            }
        }
        return parent::_log();
    }
}

您可以自定义$_exceptionClasses 数组以捕获您想要的异常并将它们发送到不同的日志。 _getMessage() 方法已被简化以删除属性。

结果

/exploitable-plugin 等随机 URL 现在将登录到 tmp/logs/404.log

2015-04-01 16:37:54 404: /exploitable-plugin Not Found
Stack Trace:
#0 /var/example.com/app/index.php(146): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
#1 {main}

【讨论】:

  • 效果很好,但还需要在上面定义异常配置的 core.php 中添加App::uses('MyCustomErrorHandler', 'Lib/Error');
  • 为了澄清 isick 的评论,如果您添加了 AppErrorHandler 作为您的新处理程序,您应该添加 App::uses('AppErrorHandler', 'Lib/Error'); -- 而不是 "MyCustomErrorHandler"
【解决方案4】:

我假设您的查看者从搜索引擎的结果中点击了这些页面。由于您是此页面的网站管理员,您可以尝试使用 Google 删除工具 https://www.google.com/webmasters/tools/removals 之类的工具。因此,这些页面将不再有任何点赞。时间成本有点高,但我看不到一种方法可以从日志记录中排除丢失的控制器操作。

无论如何,这里有关于登录 CakePHP 的一切:https://www.google.com/webmasters/tools/removals?pli=1

编辑:

其实我已经找到了一个方法,但是如果你忘记了它可能会给你带来麻烦。将此添加到 bootstrap.php 的末尾:

$matches = array();
preg_match('/^\/(.+?)\//', $_SERVER['REQUEST_URI'],$matches);
if(!App::import('Controller', $matches[1])){
   die('404 Error![some_random_chars_so_you_can_easy_find_it_in_the_future]') ;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 2018-04-30
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    相关资源
    最近更新 更多