为什么对象中的私有变量“可见”来自外部世界?

时间:2011-10-24 23:13:18

标签: php class object

给出这个例子:

class Database
{
    private $host,
            $database, 
            $username, 
            $password,
            $type;

    public $active_connection;

    //Some methods
}


class Page
{
    private $db;


    public function __construct($id)
    {
        // Some code

        $this->db = new Database($id);
    }

    //Some Methods
}


$page = new Page(0);

var_dump($page);

这将输出数据库对象的私有变量,即使它们被标记为私有(因此,据我所知,外部世界无法使用)。

我的问题是:

  1. 这是安全隐患吗?
  2. 有没有办法有效隐藏那些标记为私有的变量?
  3. 提前致谢

    编辑: 在此项目中,管理部分将提供创建自定义PHP脚本以作为部分合并到站点中的功能。由于这是开发给第三方实体,我担心的是,由于某种原因,客户无意中转储$ page对象(在我们的代码中,是主要的可修改对象)以便“探索”它。 / p>

7 个答案:

答案 0 :(得分:6)

封装是一种架构机制,而不是安全措施,不能这样使用。

攻击者究竟会如何利用此安全风险?它只能从源代码内部访问,因此他也可以读取受保护类的源代码或项目中的任何其他源代码。

此外,即使在C ++中,您也可以通过准备一个在对象中具有正确偏移量的指针来访问私有成员。

答案 1 :(得分:4)

var_dump()显示它们,因为它很特别。您还可以使用Reflection API挖掘私有/受保护的属性。

echo $ object-> _somePrivateVar;

另一方面,不会公开_somePrivateVar。

1)这是一个安全问题吗?一点也不。如果你不相信你正在执行的代码,你就会非常自豪。

2)隐藏它们是什么?它们已根据类系统的数据可见性规则隐藏。但语言是动态的,并提供了一些其他方式来窥视内部。正如列昂尼德在他的回答中所说,这是一种建筑机制,而不是安全特征。

答案 2 :(得分:4)

PHP 5.6 中引入了新的Magic方法__debugInfo(),允许您在转储对象时修改var_dump()的默认行为。

查看documentation

示例:

<?php
class C {
    private $prop;

    public function __construct($val) {
        $this->prop = $val;
    }

    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));
?>

<强>返回:

object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}

虽然这个问题已经有3年了,但我相信将来会有人发现它有用。

答案 3 :(得分:2)

var_dump旨在供开发人员跟踪和调试代码。来自documentation

  

在PHP 5中,对象的所有公共,私有和受保护属性都将在输出中返回。

答案 4 :(得分:1)

这是var_dump(以及print_rvar_export)的记录行为。这是为了让您了解正在运行的代码;例如,在调试它时,您可能想知道私有变量的值。

您可以使用输出控制功能捕获输出,或者如果您需要在另一个类中使用私有变量的内容,请使用var_export。这将是一个不寻常的情况:无论如何,你最有可能在这种情况下使用公共变量。如果您正在开发某种需要验证私有变量内容的测试套件,那么这就是您的答案。

答案 5 :(得分:1)

我知道这是一个老问题,但我想指出一种(相当)有效的掩盖变量的方法;

你可以在类中创建一个包含静态变量的函数;如果你有一个变量,你真的觉得需要从系统本身隐藏它,将它保存到函数的静态变量中。只要该函数对于类是私有的,就很难窥视内部。还行吧。如果由于某种原因,您的服务器正在将值转储到用户空间而您无法控制它。

但是像TimDev说的那样:如果你不相信你正在执行的代码,那就表明你有一些更大的安全问题。即使您有一个基于插件的项目与潜在的恶意插件作者,您也无法在该环境中保护自己。由安装这些插件的管理员来确保安全性。

答案 6 :(得分:0)

查看__debugInfo() magic method in PHP manual如何隐藏堆栈跟踪中的敏感数据(在PHP 5.6.0中添加)。这是一个例子:

class PDO_Database
{
    private $db_user = 'my_user';
    private $db_password = 'my_password';

    /**
     * The purpose of this method is to hide sensitive data from stack traces.
     *
     * @return array
     */
    public function __debugInfo()
    {
        $properties = get_object_vars($this);

        $hidden = [
            'db_user' => '***',
            'db_password' => '***',
        ];

        return $hidden + $properties;
    }
}