CKFinder 3 - PHP 连接器文档
调试和日志记录

介绍

有时 CKFinder PHP 连接器可能无法正常工作。这可能是由于配置无效、权限不足、缺少 PHP 扩展等原因造成的。在这种情况下,连接器将发送一个默认情况下只包含有关错误的常规信息的响应。

错误可能发生在不同的阶段

  • 当应用程序启动并且 CKFinder 无法正确初始化时,这可能会导致 UI 无法渲染(启动错误)。
  • 当应用程序正确初始化并且用户尝试在 CKFinder 中执行操作时(常规错误)。

使用通用错误消息是因为它们不会泄露任何可能被恶意意图的黑客滥用的潜在有害信息(如服务器路径)。

根据具体情况,通用错误消息可能不足以让配置 CKFinder 的开发人员理解发生的具体错误以及原因。本文解释如何从这种情况下恢复。

示例 1 - 启动错误

当启动 CKFinder 并将其配置为使用不存在的文件夹并且 CKFinder 没有足够的写入权限来创建它时,它将返回一个通用错误消息

未找到文件夹。请刷新并重试。

由于错误发生在应用程序启动过程中的早期阶段,因此应用程序将无法加载。由于无法访问文件系统,CKFinder 实际上无法显示任何文件,因此用户只能看到通用错误消息。

示例 2 - 常规错误(文件重命名失败)

CKFinder 已正确配置,文件已正确列在 CKFinder 中,用户可以查看文件。

当用户尝试重命名文件,但文件权限不允许这样做时(例如,因为其中一个文件夹在 Linux 上具有root 所有者),CKFinder 将显示一个通用错误消息

由于文件系统权限限制,无法完成请求。

示例 3 - 常规错误(文件上传失败)

CKFinder 已正确配置,文件已正确列在 CKFinder 中,用户可以查看文件。

当用户尝试上传文件,但文件权限不允许这样做时(例如,当 SELinux 阻止它或因为文件夹权限设置为0755 并且目标文件夹的所有者与 Web 服务器进程运行的用户不同),CKFinder 将显示一个通用错误消息

由于文件系统权限限制,无法完成请求。

调试

如引言中所述,通用错误消息可能不足以让配置 CKFinder 的开发人员使用。

幸运的是,有两种方法可以指示 CKFinder 返回有关失败原因的更有意义的信息

  • 通过更改debug 配置选项。
  • 通过更改config.php 中内置的 PHP 错误报告设置。

这两种方法是无关的,可以分别配置。

调试模式

可以在config.php 中使用以下命令启用调试模式

$config['debug'] = true;

更改此设置后,CKFinder 连接器将使用Monolog 记录器将所有服务器端错误记录到debugLoggers 配置选项中指定的处理程序中。默认情况下,CKFinder 将使用FirePHP 处理程序将详细错误记录到 CKFinder 日志文件、错误日志文件(服务器日志)和浏览器控制台。

CKFinder 日志文件

默认情况下,日志文件位于私有 CKFinder 文件夹中。请注意,仅当日志文件存储在本地文件系统后端时,日志记录到文件才有效。

缺点

  • 如果文件夹配置不当,它可能会通过 URL 公开访问,从而泄露大量信息。
  • 如果存在权限问题,CKFinder 可能无法创建或写入此日志文件。

优点

  • 日志文件仅供 CKFinder 使用,因此无需额外努力即可找出问题所在。

服务器日志(错误日志)

文件位置取决于服务器配置。对于 Apache,它通常位于以下位置

  • /var/log/httpd/error_log
  • /var/log/apache2/error.log
  • /var/log/httpd-error.log

对于 XAMPP 服务器,PHP 错误日志是一个单独的文件,默认情况下位于C:\xampp\php\logs\php_error_log(在 5.6.3 版本上检查过)。

缺点

  • 它被所有 PHP 应用程序使用,因此需要先过滤掉 CKFinder 记录的错误。
  • 在某些情况下,例如使用共享主机服务时,您可能无法访问此文件。

优点

  • 它安全可靠。
  • 它使您有机会调查过去发生的并由最终用户稍后报告的问题。

FirePHP

为了查看传递到 FirePHP 的错误,您只需在浏览器中安装相应的扩展

之后,您可以重试导致错误的操作,在控制台中您应该会看到详细的错误描述,包括异常堆栈跟踪。

注意:出于安全原因,在生产服务器上启用debug 模式应仅与将debugLoggers 配置选项设置为error_log 结合使用。这将使您能够调查由用户报告的过去发生的错误,同时确保错误不会被其他人看到。

PHP 错误报告

PHP 具有内置功能,可以帮助您理解代码执行失败的原因

在开发服务器上工作时,您可以使用 Web 服务器加载的php.ini 文件配置error_reportingdisplay_errors(确保在应用更改后重新启动服务器)。在这种情况下,启用display-startup-errors 也是一个好主意。

在生产服务器上,强烈建议不要启用display_errors 选项,因此更方便的方法是在 CKFinder 使用的config.php 文件中直接设置 PHP 错误报告。

示例 4 - 生产环境设置

以下设置默认情况下在config.php 文件中设置。不会打印 PHP 错误。

// 生产
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
ini_set('display_errors', 0);

示例 5 - 开发环境设置

以下设置在开发环境中调试问题时可能更方便。默认情况下,这些设置也存在于config.php 文件中,但已注释掉。

// 开发
error_reporting(E_ALL);
ini_set('display_errors', 1);

注意:确保仅在调试失败原因时启用display_errors。将 CKFinder 移动到生产环境后将其禁用。

如何使用?

通过设置display_errors 允许 CKFinder 打印错误有一个负面后果:它将破坏 JSON 响应。这意味着 CKFinder UI 将不再理解来自服务器的响应。这就是它使用有限的原因,它主要用于检测致命错误、超时等,而使用调试模式 无法带来令人满意的结果。

示例 6 - 调试启动错误

让我们调查示例 1 中 CKFinder 无法加载的错误。

当 CKFinder 启动时,它会向服务器发送 Ajax 请求以获取有关文件夹和文件的 信息。它发送的第一个请求是Init

CKFinder 调用的确切 URL 可以您最喜欢的浏览器的开发人员控制台中的网络选项卡中查看。它应该类似于

http://example.com/ckfinder/core/connector/php/connector.php?command=Init&lang=en

当发生示例 1 中的情况时,您将看到类似于以下内容的 HTTP 响应

{"error":{"number":116,"message":"Folder not found. Please refresh and try again."}}

现在让我们调试一下这个问题

  1. 编辑config.php 并将错误报告设置为开发
    // 开发
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
  2. 重新加载Init 命令的 URL
    http://example.com/ckfinder/build/connector/php/connector.php?command=Init&lang=en
  3. 结果现在应该包含更多信息,解释了应用程序无法启动的原因

致命错误:未捕获的异常“Exception”,消息为“后端“default”的根文件夹未找到(/home/joe/www/example.com/ckfinder/userfiles/)”,位于 /home/joe/www/example.com/ckfinder/core/connector/php/vendor/cksource/ckfinder/src/CKSource/CKFinder/Backend/Adapter/Local.php:58 堆栈跟踪:(...)

感谢错误消息,您知道哪个文件夹不存在(/home/joe/www/example.com/ckfinder/userfiles/)。应该创建该文件夹,并为其设置适当的权限。

示例 7 - 调试文件上传失败

让我们调查示例 3 中文件无法上传的错误。

当 CKFinder 上传文件时,它会使用类似于以下内容的 URL 向服务器发送 POST 请求

http://example.com/ckfinder/core/connector/php/connector.php?command=FileUpload&lang=en&type=Files&currentFolder=%2F&Flowers%2F&hash=9a3c49d939a945d7&responseType=json

当发生示例 3 中的情况时,在您最喜欢的浏览器的开发人员控制台的网络选项卡中,您将看到类似于以下内容的 HTTP 响应

{"resourceType":"Files","currentFolder":{"path":"\/Flowers\/","acl":1023,"url":"\/ckfinder\/userfiles\/files\/Flowers\/"},"fileName":"red-rose.jpg","uploaded":0,"error":{"number":104,"message":"由于文件系统权限限制,无法完成请求。"}}

现在让我们调试一下这个问题

  1. 编辑 config.php 并将错误报告设置为开发模式,就像前面的示例一样
    // 开发
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
  2. 尝试再次上传文件。
  3. 结果现在应该包含更多信息,解释为什么文件无法上传

警告: fopen(/home/joe/www/example.com/ckfinder/userfiles/files/Flowers/red-rose.jpg): 无法打开流: 权限被拒绝 在 /home/joe/www/example.com/ckfinder/core/connector/php/vendor/league/flysystem/src/Adapter/Local.php109

警告: chmod(): 没有此文件或目录 在 /home/joe/www/example.com/ckfinder/core/connector/php/vendor/cksource/ckfinder/src/CKSource/CKFinder/Backend/Adapter/Local.php144

您可以看到 /home/joe/www/example.com/ckfinder/userfiles/files/Flowers/权限被拒绝错误是导致上传失败的主要原因。

修复该文件夹的文件权限应该可以解决问题。