替代curl需要文件而不是allow_url_fopen的方法是什么?

3

我有一个PHP脚本,想要从一个网站的数据库中提取一些数据,并在另一个网站上显示它。我需要引用一些文件,但由于出于安全原因,我的allow_url_fopen被设置为关闭状态,因此使用require filename.php会抛出错误。是否有一种替代方法可以使用cURL来“require”文件?

旧例子:

<?php require ('http://site.com/filename.php'); ?>

我尝试了这个,但它不起作用:
<?php
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, 'http://site.com/filename.php');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
curl_close($ch);

// display file
require $file_contents;
?>

据我所知,您实际上无法require/include文件的内容。这些命令只接受文件路径。 - WoodrowShigeru
6个回答

2

拉姆齐女士,

2011年最广泛接受的解决方案是使用所谓的RESTful架构,这是由雅虎几年前首次广泛倡导的。它非常简单,很快你就会发现。

首先,在“服务器”端(即您接收信息的地方),您创建一个简单的RESTful服务器,我能想到的最简单的一种是(在此编码):

// RESTful service
$action = 'action_' . filter_input(INPUT_GET, 'action', FILTER_SANITIZE_STRING);
$params = filter_input(INPUT_GET, 'params', FILTER_SANITIZE_STRING);

if (function_exists($action))
{
    // Run the action w/ the parameters
    $data = call_user_func_array($action, json_decode($params));

    // Encode the data in a HTTP friendly way...
    $output = json_encode($data);

    echo $output;
}
else
{
    trigger_error('Invalid action: ' . htmlspecialchars($action), E_USER_ERROR);
}


function action_foo($param1)
{
    return "Param 1: $param1";
}

现在,在客户端,你只需这样做:
$ch = curl_init();
$params = json_encode(array('param1' => 'value', 'param2' => 'value'));
curl_setopt ($ch, CURLOPT_URL, 'http://site.com/restServer.php?action=foo&params=' . $params);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);

$data = json_decode($output);

它实际上运行得非常好。

我希望您选择我的答案!


只是为了让您(以及未来的读者)知道:这个命令会破坏字符串,所以您必须在应用filter_input之前先使用json_decode - WoodrowShigeru

0

如果两个站点都在你的控制之下,那么这将更多地成为一个速度问题而非实际的安全风险。如果你认为这是内容,那么我建议只使用回显或 <iframe> 解决方案。

但无论如何,尝试通过 .htaccess 启用 url fopen 包装器 php_flag allow_url_fopen 1,以简化操作。
否则,你的 curl 方法看起来还不错。然而 require 并不适用于字符串内容,而仅适用于文件。实际上,你所尝试的是:

eval($contents);

为避免负面影响,您可以使用以下方法:

require(file_put_contents(tempnam("/tmp", "rem_"), $contents));

0

不要试图包含远程文件,这是一个巨大的安全风险 - 只需让该远程文件生成所需的数据并将其作为序列化/JSON编码/XML字符串(以最简单的方式)发送即可。

想象一下如果远程服务器被攻击并且该文件被替换为恶意代码会发生什么。现在你已经下载了敌对代码并在你的服务器上执行它。远程代码加载从来都不是一个好主意,即使环境完全受控制。


这听起来是个好主意,但听起来很复杂!当涉及到php和编程时,我完全是个新手。 - RodeoRamsey

0

恐怕那样做行不通。通过curl获取php文件时,您获取的不是php源代码,而是生成的输出。唯一可行的方法是通过curl获取php文件的源代码(例如将php文件保存为.txt),但如果操作不当,这将带来巨大的安全风险,所以说实话我建议您最好放弃这个想法!


0
如果你只是想显示远程产生的输出,那么在你的curl调用之后,你可以直接使用echo $contents;。这本身相对无害,只要你信任该源为用户生成输出即可。
其他人所说的关于远程require/include的危险完全正确,无论什么情况下都不应该尝试这样做。

实际上,在这种情况下,我的网站将是“远程”的。我正在尝试开发一种方法,允许其他“姐妹站点”显示我网站提供的一些数据,而这不仅仅是RSS /基本XML类型的东西。 - RodeoRamsey
获取数据并回显仍然比使用require/include要好得多。在这种情况下,这是最佳实践的问题。 - Charles

0

虽然我保证远程包含代码存在风险,但有时候无法避免。

因此,与其说“不行,就这样”,实际上考虑可能性对于共同利益更好。

首先,您应该直接通过IP获取远程数据,而不是使用DNS。这将大大减少攻击面。

下一个建议是通过安全(SSL)连接阅读此内容 - 这是最好的选择。请注意,您可以使用自己的证书。重要的是连接是加密的。

至于在本地执行代码,有几种方法:

  • 使用eval:简单易用,但会严重影响性能。
  • 保存到文件并要求它:我建议使用这个。确保您使用随机文件名来隐藏代码,以免被窥探。或者将其保存在文档根目录之外。这是使用缓存机制的绝佳机会。

结论

https://123.145.168.190/file.txthttp://mydomain/file.txt更安全,即使安全证书是您自己的个人证书。虽然您可能希望在curl中禁用证书验证-这很容易做到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接