PHP:是否有安全的方法提取($\u POST)

PHP:是否有安全的方法提取($\u POST),php,Php,是否有一种安全的方法可以自动分配已发布数组中的键?下面是两个错误方法的例子 foreach( $_POST as $key => $value ) { $$key = $value; } 或 是否有更好的方法,或者最好是编码: $foo = $_POST('foo'); $bar = $_POST('bar'); .... 我表格上的50条输入信息 (发布的信息将被插入到数据库中)。虽然最好使用$\u POST['variablename']来引用这些信息,但也可以只展开所需

是否有一种安全的方法可以自动分配已发布数组中的键?下面是两个错误方法的例子

foreach( $_POST as $key => $value ) {
     $$key = $value;
}

是否有更好的方法,或者最好是编码:

$foo = $_POST('foo');
$bar = $_POST('bar');
....
我表格上的50条输入信息


(发布的信息将被插入到数据库中)。

虽然最好使用
$\u POST['variablename']
来引用这些信息,但也可以只展开所需的变量

$expected = array('name', 'telephone', /* etc */);
foreach ($_POST as $key => $value) {
  if (!in_array($key, $expected)) {
    continue;
  }
  ${$key} = $value;
}
或者,我更喜欢这样:

foreach ($_POST as $key => $value) {
  switch ($key) {
    case 'name':
    case 'telephone':
    /* etc. */
      ${$key} = $value;
      break;
    default:
      break;
  }
}

一次提取所有输入字段的更谨慎的方法是:

extract( $_POST, EXTR_OVERWRITE, "form_" );
这样,您的所有输入变量将至少被称为
$form\u foo
$form\u bar
。避免在全球范围内这样做——不是因为全球是邪恶的,而是因为没有人在那里清理

但是,由于大多数情况下都是在本地化范围内执行此操作,因此,如果您仅需要输出的所有字段,也可以应用htmlentities:

extract(array_map("htmlspecialchars", $_POST), EXTR_OVERWRITE, "form_");

做这件事没有单一的理由。
要处理用户输入,数组比单独变量好100倍

A将变量提取到局部范围的安全方法是。您正在将变量注入到本地范围中,无论您如何操作,这都是一个问题。即使现在将变量限制为几个选定的变量,这些变量不会与作用域中的其他变量名冲突,但如果开始向表单中添加元素,以后可能会遇到麻烦


数组专门用于在不拥挤变量名称空间的情况下保存无限数量的命名值。使用它们!你可能需要多打字,但这是课程的标准。

< P>我喜欢一种方法,让你在课堂上用动态的吸气剂和固定器为你做所有的工作。下面是我将如何编写代码

首先,创建一个bass类来保存数据:

class FormParameterHandler {
  protected $parameters;
  public function __construct($associative_array) {
    $this->parameters = array();
    foreach($associative_array as $key => $value) {
      $this->{$key} = $value;
    }
  }
  public function __get($key) {
    $value = null;
    if(method_exists($this, "get_$key")) {
      $value = $this->{"get_$key"}();
    } else {
      $value = $this->parameters[$key];
    }
    return $value;
  }
  public function __set($key, $value) {
    if(method_exists($this, "set_$key")) {
      $this->{"set_$key"}($value);
    } else {
      $this->parameters[$key] = $value;
    }
  }
}
接下来,创建一个特定的类,用于某些特定的表单,其中有一些特殊的内容需要验证。作为一名程序员,您可以在这里自由地以任何方式实现它。请记住,由于我们使用反射来查找setter方法,我们可以为已知的问题区域编写特定的setter方法,例如,在“注册用户”表单中检查相同的密码:

最后,在“register user”流中使用派生类,以轻松找出输入的两个密码是否匹配:

$registerFormParameterHandler = new RegisterFormParameterHandler($_POST);
if($registerFormParameterHandler->has_equal_passwords()) {
  print "are equal";
  //register user
} else {
  print "are not equal";
}
您可以通过创建一个HTML表单来测试这一点,该表单有一个名为“password”的输入字段和另一个名为“password\u repeat”的输入字段

要访问任何表单数据,请使用表单数据对象变量名,后跟访问运算符“大于“->,后跟参数名。在上面的示例中,如果有一个名为“user_name”的输入字段,则可以通过调用

$registerFormParameterHandler->user_name
Rr,如果已定义要在其他变量中获取的字段的名称,请使用反射:

$registerFormParameterHandler->{$settings['form_data_user_name']}

玩得开心!:)

问题的答案取决于程序员的计算机、语言和安全知识。处理$u POST的开始顺序有点像国际象棋游戏中的开始动作。许多人使用
foreach
循环,却没有意识到
foreach
将按照您使用的方式复制$\u POST的内容(编程PHP:第5章,第128-129页)。如果您仅仅通过使用
foreach
导致缓冲区溢出,这不是很有趣吗

一位评论员暗示,一切都应该在
$\u POST
超级全局中处理。这有一些优点。。。但是,暂时忘记缓存,访问数组值比直接访问变量慢

由于您要验证五十(50)个控件(可能包含大量内容),我可能不想让阵列访问性能的影响超过50次(原始访问的影响)。此外,如果您担心编写安全的输入验证例程,那么将脏衣服(未验证的输入)与干净衣服(验证的输入)分开是一个好主意。这就是说,您可能需要一个干净的数组(因此$u POST advocate的响应),但至少您通过将希望的好与潜在的坏分开来降低过程中的风险

是否有一种安全的方法可以自动分配已发布数组中的键

我可以这样开始:

此示例的函数库




请注意,我使用
$controlNames
数组准备东西,因此我不必向
$\u POST
请求密钥。毕竟,我应该认识他们!:-)两个用户定义的函数,
all\u controls\u submitted()
all\u controls\u set()
是在尝试使用
$\u POST
中的任何值之前应该问的两个基本问题。诚然,我确实在
所有提交的控件()
中使用
$\u POST
,但只获取提交控件的名称,而不是值

$postKeys = array_keys($_POST);
然而,谁能说控件名称本身不会有毒,需要输入验证?!!$\u服务器中的值也是如此。看,一场象棋比赛

是否有一种安全的方法可以自动分配已发布数组中的键?我不能肯定地告诉你,但也许上面的代码可以帮助你?至少你有钥匙


编程PHP:第5章,第125页

试试这个内置的方法/函数
过滤输入


参考URL:

最好用
$\u POST['variablename']
来参考它们。问题是,之后你想用它们做什么。你的两个版本都只是试图重新创建完全愚蠢的PHP“register\u globals”。负责这项工作的原始PHP开发人员的父母本应被烧死在火刑柱上,以防止其产生。@Alistair:取决于所使用的前缀,如果前缀与任何变量的开头匹配,仍然可以获得意外/受污染的覆盖。@AbiusX:通常,我会将它们插入到
$registerFormParameterHandler->{$settings['form_data_user_name']}
function all_controls_submitted($controls) {
  $postKeys = array_keys($_POST);
  foreach($controls as $key) {
    if(! array_key_exists($key, $postKeys)) {
      return false;
    }
  }
  return true;
}

function all_controls_set($controls) {
  foreach($controls as $key) {
    if(! isset($_POST[$key])) {
      return false;
    }
  }
  return true;
}
if(is_array($_SERVER) && isset($_SERVER['REQUEST_METHOD'], $_SERVER[REQUEST_URI]) && $_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/contact.php') {
  $newForm = true;
} elseif (is_array($_SERVER) && isset($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/contact.php') {
  $newForm = false;
  $controlNames = array('firstName', 'lastName', 'e-mail', 'company', 'subject', 'message', 'captcha');
  define('NUM_CONTROLS_EXPECTED', count($controlNames)); //Seven (7)
  if(is_array($_POST) && count($_POST) === NUM_CONTROLS_EXPECTED && all_controls_submitted($controlNames) && all_controls_set($controlNames)) {
    //Begin input validation
  }
} else {
  header('location: http://www.nsa.gov');
}
$postKeys = array_keys($_POST);