Суперглобальные массивы и register globals

PHP ранних версий работал с данными, приходящими от пользователя, следующим образом.

Массивов $_GET, $_POST и т.п. не было. Все данные записывались в глобальные переменные. Например, значение поля name из GET-формы попадало в переменную $name, IP-адрес посетителя - в переменную $REMOTE_ADDR, и т.д. Порядок заполнения переменных - что немаловажно, так как GET-формы, POST-формы, серверные переменные и т.д. - определялся следующим образом:

  • Переменные среды окружения (environment)
  • GET-параметры (QUERY_STRING)
  • POST-форма
  • Данные из cookies
  • Серверные данные (переменные REQUEST_URI, REMOTE_ADDR и т.п.)

При этом следующие данные "затирают" предыдущие, то есть, значение поля GET-формы с именем REMOTE_ADDR будет перезаписано одноименной серверной переменной, содержащей IP-адрес посетителя.

Эта последовательность настраиваема с помощью конфигурационной переменной в php.ini, но в ее изменении нет никакой необходимости: указанный порядок наиболее разумен. Регистрирует ли PHP эти глобальные переменные, зависит от настройки register_globals в php.ini. Во времена PHP3 никто и не думал отключать ее - настройка register_globals=on была общепринятым стандартом.

Конечно, написание скриптов при таком подходе становится максимально простым - как назвал поле формы, такую переменную и смотри. А если уж нужно брать информацию из конкретного места - есть массивы $HTTP_GET_VARS и им подобные (которыми при таких длинных названиях и необходимости явного объявления видимости внутри функций с помощью global мало кто пользовался). Это все прекрасно для небольших скриптов строк по 50-100. Но в объемных программах такой подход приводит к путанице: поди упомни, откуда какая переменная. Что еще хуже, такой способ программирования допускает серьезные ошибки, приводящие к огромным дырам на сайте. Пример (утрированный, конечно, но аналогичным образом были взломаны сотни сайтов):

<?
if (проверка_имени_пользователя_и_пароля()) {
$auth = true;
}
 
if ($auth == true) {
доступ_к_администрированию();
}
?>

Вводим в адресной строке http://адрес/скрипт.php?auth=1 - и, благодаря register_globals=on - получаем доступ к администрированию, не зная паролей.

Конечно же, разработчики PHP не могли не отреагировать на существование данной проблемы:

В версии PHP 4.1.0 ввели $_XXX - массивы, называемые суперглобальными, и рекомендовали установить register_globals=off и пользоваться данными массивами. По их именам очевидно их назначение:

  • $_GET
  • $_POST
  • $_COOKIE
  • $_SERVER
  • $_ENV
  • $_SESSION (для работы с сессиями - тут есть своя специфика)
  • $_REQUEST ($_COOKIE + $_POST + $_GET)

В версии PHP 4.2.0 установили значение по умолчанию register_globals=off.

Проблеме register_globals также посвящена страница http://www.phpfaq.ru/globals. Если вы привыкли к register_globals=on, или вам надо "завести" старый скрипт, написанный 8 лет назад - там все подробно разжевано.

Реклама