提问人:Jonathan Coe 提问时间:1/4/2012 最后编辑:AbraCadaverJonathan Coe 更新时间:3/13/2021 访问量:1379
在 PHP 中使用变量是不好的做法吗?
Is it bad practice to use variable variables in PHP?
问:
例如,一个简单的 MVC 类型系统:
/api/class/method
使用 重写为 PHP 变量,然后执行如下操作:.htaccess/nginx.conf
<?php
// Set up class + method variables
$className = some_class_filter($_GET['class']);
$method = some_method_filter($_GET['method']);
// Check if class exists and execute
if(file_exists(BASE . "/controllers/" . $className . ".class.php")) {
require BASE . "/controllers/" . $className . ".class.php";
$$className = new $className();
// Execute the method
$$className->$method();
} else {
// Spit out some error based on the problem
}
?>
这是可怕的坏做法吗?如果这是不好的做法,有人可以解释为什么吗?如果是这样,有没有更好的方法来做我正在做的事情?
编辑从本质上讲,我使用变量的原因是为了简化扩展核心系统 - 即 - 添加新控制器既好又简单。我绝对理解允许基本上任何函数或类在没有某种过滤器的情况下实例化的安全风险。
“some_filter_here”可以是允许的控制器列表 - 正如这里的一些人所提到的白名单。
答:
既然你正在编写“some_class_filter”和“some_method_filter”代码,我会说没关系。你也有一个错误或默认处理程序,我看到,所以最后,我会说没关系。
我相信许多 MVC 框架都以类似的方式运行。
是的,这是相当糟糕的做法。该实例是否需要变量变量?换句话说,您是否需要在给定的请求中实例化多个类和方法?您的 URI 结构表明不是。如果没有,您可以使用:
$object = new $className();
$object->$method();
否则,您可能需要执行以下操作:
$objects = array();
$objects[$className] = new $className();
$objects[$className]->$method();
这避免了变量对范围的污染,因为变量更难跟踪。
就给定目录中是否存在检查您的类而言,这应该是一个足够的白名单(假设攻击者无法写入该目录)。
编辑:作为进一步的检查,您可能需要考虑在调用该方法之前检查对象上的method_exists
。
评论
它们不是可取的,但可以随心所欲地使用它们。
不过,有几个提示:您的代码确实存在一个漏洞,攻击者可以使用 .如果该文件存在,则调用将返回,应用程序将尝试包含该文件并将其实例化为类。$_GET
?class=../base
file_exists()
true
安全的情况是将这些参数列入白名单,仅为字母、数字和下划线(如果您用下划线分隔单词,即 )。.php
另外,我更喜欢使用 和 的语法。在代码中使用这些函数将如下所示:call_user_func
call_user_func_array
<?php
$class_name = $_GET['class'];
$method_name = $_GET['method'];
$parameters = $_GET;
unset($parameters['class'], $parameters['method']); // grabs any other $_GET parameters
if (file_exists(BASE.'/controllers/'.$class_name.'.class.php')) {
require BASE.'/controllers/'.$class_name.'.class.php';
$controller = new $class_name();
$response = call_user_func_array(array($controller, $action_name), $parameters);
}
else {
header('HTTP/1.1 404 Not Found');
// ...and display an error message
}
评论
上一个:PHP 变量变量不覆盖原始变量
评论
$$className = new $className();