php - 根据用户输入创建一个类

标签 php

要求 $input 是不安全的。 '.php'。然后开设一个类(class)。我怎样才能使它安全,而不需要使用可以启动的类的白名单。

Ex 1.(错误代码)。

<?php

$input = $_GET['controller'];

require $input . '.php';

new $input;

?>

最佳答案

免责声明

首先我应该说,在您的系统中定义静态路由在设计上是安全的,而这个答案,即使我已经努力缓解安全问题,也应该在信任其操作之前进行彻底的测试和理解。

基础知识

首先,使用取自 the manual 的正则表达式确保 Controller 包含有效的变量名。 ;这消除了明显的错误条目:

$controller = filter_input(INPUT_GET, FILTER_VALIDATE_REGEXP, [
    'options' => [
        'regexp' => '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/',
        'flags' => FILTER_NULL_ON_FAILURE,
    ]
]);

if ($controller !== null) {
    // load and use controller
    require_once("$controller.php");
    $c = new $controller();
}

执行层次结构

这很好用,但是如果有人尝试加载内部类怎么办?它可能会导致应用程序严重失败。

您可以引入所有 Controller 必须扩展或实现的抽象基类或接口(interface):

abstract class Controller {}

// e.g. controller for '?controller=admin'
class Admin extends Controller {}

顺便说一句,为避免名称冲突,您可以在单独的命名空间中定义它们。

这就是你将如何实现这样的层次结构:

if ($controller !== null) {
    // load and use controller
    require_once("$controller.php");
    if (is_subclass_of($controller, 'Controller')) {
        $c = new $controller();
    }
}

我正在使用 is_subclass_of()在实例化类之前进行类型检查。

自动加载

在这种情况下,您可以使用自动加载器,而不是使用 require_once():

// register our custom auto loader
spl_autoload_register(function($class) {
    $file = "$class.php"; // admin -> admin.class.php
    if (file_exists($file)) {
        require_once $file; // this can be changed
    }
});

这也是您可以规范化类名的地方,以便它更好地映射到文件名,并强制执行自定义命名空间,例如"App\\$class.php".

这将代码减少了一行,但使加载更加灵活:

if ($controller !== null) {
    // check hierarchy (this will attempt auto loading)
    if (class_exists($controller) && is_subclass_of($controller, 'Controller')) {
        $c = new $controller();
    }
}

所有这些代码都假定您有适当的错误处理代码;对于实现建议,您可以查看 this answer .

关于php - 根据用户输入创建一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16102083/

相关文章:

php - 具有 RESTful 身份验证的 Symfony2 应用程序,使用 FOSRestBundle 和 FOSUserBundle

php - wc_get_products 返回空数组?

php - 我如何从数据库中删除除最近 24 小时 UNIX 时间格式之外的数据

php curl -k 或 --insecure, -X

php - Recyclerview MySql int 显示 0

php - Mysqli 多表操作

php - 比较值顺序不同的两个数组

php - 如何使用php从Mysql中提取Json数据

php - 使用 javascript 将下拉框的值设置为最后提交的值

javascript - 音频html5循环暂停