Емулация на register_globals на директива
Има такава интересна директива в PHP, наречена register_globals, дефинирана в php.ini. Директивата казва на компилатора, че стойностите на входящите (глобални) променливи трябва да бъдат премахнати от техните системни масиви и представени като независими променливи. Такива данни включват всичко, което се предава на скрипта „отвън“: данни от формуляри, данни от URL адреси, бисквитки и т.н. Лично аз харесвам тази директива, защото спестява време за писане на скриптове и ги прави по-четими. Сравнете сами кое изглежда по-хубаво и удобно за окото:
Като цяло, аз лично харесвам PHP главно заради неговата четливост и бързо писане.
Въпреки това във всеки удобен чип със сигурност се крие някаква мръсотия. Не без проблеми и с регистрацията на глобални променливи. Невнимателните програмисти оставиха дупки в своите скриптове, които можеха да бъдат открити и използвани от потребителя. Просто казано, ако променлива вътре в скрипта е била използвана, но не е зададена от същия скрипт, тя може да бъде зададена „отвън“ чрез предаване на нейното име и стойност на скрипта чрез URL адрес, бисквитка или нещо друго.
Тази дупка, която е означена като "дупки в PHP" и аз лично я смятам за дупка в програмирането, а не езикова, накара разработчиците на PHP да препоръчат деактивирането на register_globals. Това, което веднага беше възприето от обществеността като ръководство за действие: всички започнаха да изключват регистрацията на глобални променливи на своите сървъри.
Може би това не е толкова лошо, няма да съдя, защото в името на безопасността понякога те изграждат и ограждат много повече от кода на самата задача.
Но общият отказ да се регистрират глобални променливи доведе до нов проблем - много скриптове трябва да бъдат пренаписани почти от нулата, защото трябва да проверите всеки ред, да намерите всичкоизползвани променливи и ги променяйте на „защитени“ двойници.
Доколкото разбирам, такава задача в крайна сметка се свежда до присвояване на стойности от глобалните масиви $_REQUEST, $_POST, $_GET, $_COOKIE, $_SERVER и т.н. към обичайните променливи в началото на скрипта.
И така, къде отивам. И ето какво. Нормалният програмист не трябва да допуска дупки в скриптовете си, подобни на дупки, базирани на автоматична регистрация на глобални променливи, но това ще тревожи ли администратора на сървъра, на който е решено да постави кода? Не, не го интересува и е прав по своему.
Следователно, ако сте написали персонализирана програма, използвайки глобални променливи, и клиентът реши да я инсталира на сървър, където регистрацията му е забранена, тогава нищо няма да работи - имате проблеми.
Ако решите да прехвърлите всичките си проекти на нов хостинг и доставчикът забранява използването на глобални променливи за регистриране, имате проблеми.
Как да бъдем? Не четете десетки, стотици, а понякога и хиляди страници код в търсене на използването на глобални променливи.
Предлагам следното решение. Просто трябва да емулирате операцията register_globals в един единствен скрипт или в началото на обектно-ориентирана структура.
Как да го направим. Да, не е много трудно. Нека помислим логично: имената на променливите и техните стойности се съдържат в съответните глобални масиви. Като правило се използва масивът $_REQUEST, който комбинира всички променливи GET, POST и COOKIE. Тези. всичко, което се предава на скрипта от браузъра, е това, с което скриптовете работят.
Така че трябва да извлечете имената на променливите, стойностите на променливите от масива и да присвоите първото на второто. Извличането не е проблем, за това е подходяща функцията за повторение на всички клетки на масиваforeach(), но как да присвоя? Ако имаме "atos" в$_REQUEST[username], как можем програмно да създадем променлива$usernameсъс стойността "atos"? Не можем да знаем предварително кои имена на променливи ще бъдат в масива $_REQUEST.
Тук е полезна невероятната функция eval(), която рядко се използва в нормалното програмиране, но е буквално незаменима в някои случаи. Струва си да пиша за самата функция отделно, така че ще кажа само няколко думи за тези, които не са запознати с нея.
Функциятаeval()кара PHP да третира обикновения текст, съдържащ се в променлива, като част от PHP код. На езика на примерите, резултатите от изпълнение на низове
Тук eval() ще ни помогне да декларираме всички променливи от масива $_REQUEST. Изглежда много кратко:
Вмъкнете този цикъл в самото начало на вашия скрипт; той ще премине през масива от глобални променливи и ще ги декларира не по-лошо от register_globals. И може би дори по-добре, защото. Има много глобални масиви и не е необходимо да изваждате променливи от всички тях. По правило данните от масива $_REQUEST са достатъчни.
Не забравяйте обаче за сигурността на вашия код. Обърнете внимание на спецификата на функцията eval() – тя ще обработи целия код, който й е подаден като параметър. Бъдете внимателни, вземете мерки за сигурност, така че нападателят да не подхлъзне част от своя php код като име на променлива или съдържание, или просто неправилни данни, които могат да причинят грешка (например име на променлива, започващо с число или друг незаконен знак).
Както можете да видите, това също е прост метод, базиран на факта, че стойността на променливата $k се използва като име на новата променлива. Удобен. Отличава се с автоматична регистрация не само на променливи, но и на масиви. В случай наметодът eval() ще трябва да провери всяка променлива за is_array() и да я разшири (регистрира) допълнително, ако имате нужда от такъв масив.
И най-простият метод е extract().
Целият код за нашия пример ще изглежда така:
Това е най-"глупавият" метод, който "разгръща" всичко, което се съдържа в масива $_REQUEST, в променливи. Няма абсолютно никаква гъвкавост в този подход - не можете да повлияете на регистрацията на променливи или да въведете някакъв контрол, но изглежда много стегнато.
И накрая, не забравяйте, че register_globals може да бъде активиран не само в конфигурационния файл на Apache, но и в .htaccess файла на вашия сайт.