【问题标题】:Securely Run Cron Jobs with Zend Framework使用 Zend 框架安全地运行 Cron 作业
【发布时间】:2011-02-28 19:34:32
【问题描述】:

我已经看过很多关于 cron 和 ZF 的帖子,但大多数解决方案都让这项工作由公众来触发。

如果您想设置一个只能由 cron 运行的操作怎么办?不是某个匿名用户,也不是必须登录的人?

我使用的解决方案涉及将一个文件放在我的 web 根目录之外,让它引导足够的 ZF 以使用我需要的东西(比如,我不需要视图),然后从 cron 中点击它。 我的问题是,这是一种“最佳实践”方式吗?如果您需要使代码可以通过网络访问,但仍需要防止随机用户找到并运行它,该怎么办?

为了说明,这是我正在做的(有效的)从 php 命令行运行的 cron 作业,并且在同一台服务器上,如下所示:

* 10 * * * php /Apps/ZF/cronjobs/crontest.php

Webroot 为:/Apps/ZF/someproject/

crontest.php:

<?php
ini_set('include_path', ini_get('include_path') . ':/Apps/ZF/someproject/library');

define('APPLICATION_PATH','/Apps/ZF/someproject/application');
define('APPLICATION_ENVIRONMENT','test');

//Include the loader (for loading ZF resources)
require_once 'Zend/Loader.php';

//Include the model (to access the Sites model in this case)
require_once(APPLICATION_PATH . '/models/Planets.php');

Zend_Loader::registerAutoload();

$configuration = new Zend_Config_Ini(
    APPLICATION_PATH . '/config/config.ini',
    APPLICATION_ENVIRONMENT
);

// DB adapter
$dbAdapter = Zend_Db::factory($configuration->database);

// DB table setup
Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);

// Whatever code we want to run... 
$test = new Model_Planets();

$test->fetchEntries();

Zend_Debug::dump($test);
?>

所以,正如我所说,这行得通,所以我不是在找人给我写一个解决方案......只是对这样做“更好”感到好奇。另外,如果我需要通过 Web 访问它,但仍然希望它只能由 cron 运行,该怎么办?如何让它更灵活(因为我在这里硬编码了一些我怀疑可以变得更加动态的路径)?

我假设我可以列出允许的服务器,然后使用 $_SERVER['REMOTE_ADDR'] 进行测试?

大家觉得呢?建议?我一个人工作,所以我没有同事可以在这方面寻求帮助......所以在某种程度上是我的同事。

【问题讨论】:

    标签: php zend-framework cron


    【解决方案1】:

    一种方法是设置环境变量。

    所以在你的 crontab 中

    SCRIPT_RUN_ENV=cron
    * * * * * foo.php // Whatever your line is
    

    然后,在应用程序中,只需检查:

    if (get_env('SCRIPT_RUN_ENV') != 'cron') {
        echo "Program cannot be run manually\n";
        exit(1);
    }
    

    现在,任何人都可以将他们的环境变量设置为该值并成功运行 cron,但它应该停止琐碎的运行(或意外)...

    但还要注意,任何可以在服务器上编辑环境变量的人都已经可以执行它,所以没有真正的方法可以从这个角度保护它(至少没有一个是自动化的)......同样值得注意的是,你无法通过 HTTP 注入环境变量。

    【讨论】:

    • 啊!我不知道你可以像这样在 crontab 中设置一个变量。这很有用,但正如你所说,任何人都可以添加这个变量......我仍然希望为整个事情提供更安全的解决方案。
    • 只有被请求的代码才属于 Web 根目录。如果网络服务器无法使用它,请将其移到网络根目录之外(包括框架库等)。只有要提供给浏览器的内容才属于那里...
    • 对,但是如果您需要从远程服务器上的 cron 实例访问某些内容(使用 wget、lynx、curl 等),您需要将其保存在 Web 根目录中。因此,使其安全的问题仍然存在。保护它是我问题中的真正问题。
    • @Shehi:我认为它使它更便携,因为它不依赖于您无法控制的 SAPI 实现细节。至少通过一个简单的环境变量,您可以完全控制它(而且它确实是 100% 可移植的)。更不用说优秀的编码员使用他/她可用的工具来解决语义上有意义的问题。如果要分发它,我同意这样做并不好。但是,考虑到一次性实现,我不认为这有点脏,但单独不好......
    • @Gaoshan:这取决于 secure 的含义。如果有人有权在本地机器上读取和执行代码,我认为不可能比这提供更多的保护。如果有人可以阅读源代码,他们就可以执行它。并且不可能通过 Web 服务器注入环境变量(除了在 Web 服务器配置中设置它)。因此,它确实尽可能地安全,并且尽可能地便携。同样,这取决于您要解决的确切问题...
    【解决方案2】:

    嗯,PHPSAPI 通过 cron 和 web-server 运行时的值应该不同。

    【讨论】:

    • +1 ,以您的方式确定环境会更好 -
    • 我刚刚测试了这个,通过 cron 的 wget 运行它,phpsapi 输出:'apache2handler'。所以 wget 将显示 apache sapi 而来自 cron 的 php 将显示 cli sapi ...似乎 cron 与它没有任何关系。
    • 这就是重点...... SAPI :) Wget 只是另一个基于文本的浏览器,它将脚本作为网站运行。 cron 将其作为客户端程序运行。
    • 但正如您在评论中所说,它与 cron 没有任何关系。 PHPSAPI 的值在通过 cron 和 webserver 运行时没有变化。运行 wget 将始终产生相同的 PHPSAPI(在这种情况下无论 apache 是什么),从命令行运行 php 也将始终产生相同的结果(cli)。是否从 cron 运行并不重要。
    • 不不不......你混淆了我的回复。你的测试结果是对的。如果您通过 wget 通过 Cron 运行它,它将影响 PHPSAPI,而不是 cron [PHPSAPI = apache2handler,正如预期的那样]。如果你从* * * * * php script.php 之类的命令行运行它,PHPSAPI 将是 = CLI。因此,如果您需要将 Cron 执行与常规浏览器区分开来,只需像这样运行它:* * * * * php script.php。不要使用 wget。我只是提供了一种方法来解决这个消歧问题。
    【解决方案3】:

    保护 php cron 作业的最佳方法是将 php 文件放在 non-public_html 文件夹中。

    例如:

    您的页面位于/home/myuser/public_html/test.php

    将其移至/home/myuser/test.php

    并投入 cron 工作:

    php -q /home/myuser/test.php
    

    现在,没有用户可以从浏览器进入您的页面,只有 cron 作业可以使用它。

    【讨论】:

      【解决方案4】:

      不是某个匿名用户,也不是必须登录的人?

      使用 x.509 客户端证书。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-23
        • 2023-04-06
        • 2012-06-03
        • 1970-01-01
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 2010-10-05
        相关资源
        最近更新 更多