【问题标题】:Contingency plan for fopen error in phpphp中fopen错误的应急计划
【发布时间】:2009-05-09 15:05:01
【问题描述】:

我正在编写一个 PHP 应用程序,该应用程序具有一个“控制面板”,可以编写一个带有某些变量的 prefs 文件。在每个POST 上,如果文件不存在,则会创建它。如果它确实存在,它是unlinked,一个新文件是touched,具有相同的文件名和新变量。然后,此文件将包含在另一个页面上,并根据其中的变量显示内容。

$file = "phpsettings.php";

if (!file_exists($file)) {
   touch($file);
  $handle = fopen ($file, 'r+'); 
$str = "<?php \$pref1 = \"$mypref\"; ?>";

} else {

unlink($file);
   touch($file);
   $handle = fopen ($file, 'r+'); 
   $str = "<?php \$pref1 = \"$mypref\"; ?>";

}

fwrite ($handle, $str); 
fclose ($handle); 

如果这个文件每天会被覆盖很多次,这是一种安全的编写首选项的方式吗?如果文件未正确保存,有什么好方法可以提醒此控制面板的用户,在这种情况下,避免破坏包含此首选项文件的页面的良好应急计划是什么?如果!(file_exists),则要填充的默认变量集?

【问题讨论】:

  • 您的问题是,“使用文件将我的用户状态存储在我的应用程序中是否安全?”
  • 考虑在 fopen 调用之后添加群调用。 php.net/flock

标签: php fopen


【解决方案1】:

如果将设置存储在数组中,则可以将它们序列化()并写入文本文件,而不是将原始 php 写入 php 文件并包含它。

如果您没有根据这些偏好清理您的输入,并且说 $mypref1 代表某人的姓名,那么没有什么可以阻止他们在表单字段中填写此内容:

\"; echo \"PWNED

你生成的 PHP 将变成

<?php \$pref1 = \"$mypref\"; echo \"PWNED\"; ?>

首先,将您的首选项存储在一个数组中并使用 serialize() 更安全:

$prefs = array('mypref1' => 'somethingorother');
$handle = fopen ($file, 'w'); 
fwrite($handle, serialize($prefs));
fclose($h);

// example code demonstrating unserialization
$prefs2 = unserialize(file_get_contents($file));
var_dump($prefs == $prefs2); // should output "(bool) true"

在您的问题中,您还提到如果该文件确实存在,则它是未链接的。您可以通过将“w”作为第二个参数传递给 fopen 来简单地将其截断为零长度 - 您不需要手动删除它。无论如何,这应该设置 mtime,不需要调用 touch()。

如果写入文件的值是首选项,那么每个首选项肯定都有一个默认值,除非有数百个? array_merge 将允许您基于每个键进行覆盖,因此如果您执行以下操作:

// array of defaults
$prefs = array(
    'mypref1' => 'pants',
    'mypref2' => 'socks',
);
if (file_exists($file)) {
    // if this fails, an E_NOTICE is raised. are you checking your server error
    // logs regularly?
    if ($userprefs = unserialize(file_get_contents($file))) {
        $prefs = array_merge($prefs, $userprefs);
    }
}

如果问题是存在堆,并且您不想将它们全部初始化,则可以有一个 get_preference 方法,它只包装对 prefs 数组的 isset 调用。

function get_preference($name, &$prefs) {
    if (isset($pref[$name]))
        return $pref[$name];
    return null;
}
var_dump(get_preference('mypref1', $prefs));

除了这引发的所有问题之外,现实情况是,对于您的应用程序,万一 确实 fopen 出现问题,无论如何它都应该被视为严重失败,如果出现问题,您可能会使用此功能的少数用户会很快与您联系。

【讨论】:

  • 如果 (a) 选项是单选按钮,而不是文本字段 - 是的,它们仍然是可操作的,但 (b) 我相信将使用的一小部分人,则此解决方案是否仍然必要这个表格?
  • 不完全是,但如果不出意外,这可能是一个很好的习惯养成练习,也是使用技术缓解注射问题的良好实践。
【解决方案2】:

最好将用户状态存储在会话中,并仅在需要时保留该状态。

【讨论】:

  • 我应该澄清一下——这不是针对个人用户的偏好,而是针对访问该页面的任何人的页面外观偏好。它们是“编辑的偏好”。
  • 所以每个用户都可以为页面设置不同的外观?
  • 不,一个授权用户从一组预定义的选项中设置页面的外观。全世界都按照用户定义的方式看待页面。
【解决方案3】:

为什么不直接使用 fopen() 的截断功能呢?我相信您需要传递“w+”而不是“r+”...如果文件存在,它将被截断,如果不存在,您只需创建一个新文件。于是代码变成了:

$file = "phpsettings.php";
$handle = fopen( $file, 'w+' );
$str = "<?php \$pref1 = \"$mypref\"; ?>";
fwrite ($handle, $str); 
fclose ($handle);

【讨论】:

    猜你喜欢
    • 2012-09-07
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    相关资源
    最近更新 更多