5

我有这个框架项目,我想强制使用一个Input类来访问所有超全局变量,比如$_POST,$_GET$_SERVER. 最近的一个问题让我想起了它。

该课程将对密钥进行一些清理,以确保没有恶意或意外,并提供一种访问项目的方法,而无需isset()每次都使用。它可能会根据配置执行其他操作,并且可能还会清除超全局变量。我也不喜欢超全局变量不是只读的这一事实,我想在值中强制执行完整性。我希望这个类被独占使用,并希望在不使用时警告开发人员。

我的问题是这样的,我担心答案是“不”:

访问超全局变量之一时是否可以触发错误?例如:

$myvar = $_POST['key'];
// Prints "Error: POST cannot be accessed directly, use the Input class instead"

或者写信给超全球?:

$_POST['key'] = 'myvalue';
// Prints "Error: POST data cannot be modified"
4

4 回答 4

6

将对象分配给 $_POST 变量并使用魔术方法怎么样?

$_POST = new %your-class%();

于 2012-10-18T12:41:41.057 回答
6

您可以使用ArrayAccess

示例 1:

$_POST = new SUPER($_POST);
$_POST['hello'] = "Hello World"; // This would trigger error ;

示例 2:a.php?var=1&var2=2

$_GET = new SUPER($_GET);
echo $_GET['var'] ; // returns 1
echo $_GET['var2'] ; // returns 2

$_GET['var3'] = 2 ; //return error

使用的类

class SUPER implements \ArrayAccess {
    private $request = array();

    public function __construct(array $array) {
        $this->request = $array;
    }

    public function setRequest(array $array) {
        $this->request = $array;
    }

    public function offsetSet($offset, $value) {
        trigger_error("Error: SUPER GLOBAL data cannot be modified");
    }

    public function offsetExists($offset) {
        return isset($this->request[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->request[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->request[$offset]) ? $this->request[$offset] : null;
    }
}
于 2012-10-18T13:03:18.493 回答
2

它只会触发通知,但如果您首先将所有超全局键/值复制到对象中,然后执行以下操作:

unset($_GET,$_POST,$_SERVER);

之后,对这些超全局变量的任何读取访问都将失败。要禁止写入,您可以在这些变量上实例化您选择的对象(即名称为 $_GET、$_POST、$_SERVER)。为了让这些通过 [$key] 数组操作符可访问,它们应该是实现ArrayAccess接口的对象的实例。

于 2012-10-18T12:45:12.850 回答
1

这基本上是@Baba 已经展示的内容,但我一直在为一些项目使用类似的输入包装器。它非常适合小型项目,但不可否认,我仍然必须克服使用不情愿。但是,它肯定会简化清理和审核。

http://sourceforge.net/p/php7framework/svn/66/tree/trunk/php7/input.php?force=True
http://sourceforge.net/p/php7framework/wiki/input/

ArrayAccess方法就是您所需要的。在运行时防止输入注入或覆盖offsetSet就足够了。虽然我只是打印通知,但仍然允许它。

然而,基本上它是用于消毒的。例如,对 eg 的任何原始访问都$_REQUEST["key"]将通过默认过滤器,但您也可以在运行时简单地调用各种过滤器链:

 print $_POST->html->text["comment"];

最近我一直在允许一个受限制的 register_globals workaorund,一次本地化多个变量。使用 PHP 5.4 语法看起来很有趣:

 extract( $_REQUEST->list->text[[ title, id, email ]] );
 // implicit undef-constant notices here ^^ of course

如果您只是在启动时包装 $_GET、$_POST、$_REQUEST,那么您已经实现了您的目标。唯一的语法缺点是您不能再使用empty($_POST),此类包装器仍允许所有其他原始数组访问。

于 2012-10-18T20:54:54.347 回答