 |
 |
Форум сетевых администраторов » Программирование » PHP » GET и POST - чем отличаются, как использовать, вопросы безопасности.
Автор |
Тема |
 |
|
 |
|
|
|
STFW
|
GET и POST - чем отличаются, как использовать, вопросы безопасности. |
[сооб. #18258]
01-08-2002 21:50 |
|
STFW


Зарегистрирован: Jul 2002
Место проживания: Кольский п-ов
Публикаций: 305
Статус:  |
GET и POST - чем отличаются, как использовать, вопросы безопасности.
| [сообщение #18258] |
Этот материал предназначен для новичков. В нем объясняется как сценарий PHP может получить данные от пользователя и что можно сделать потом.
С помошью запроса клиентская программа(броузер) может получить необходимые данные от программы сервера.
В спецификации HTTP/1.1 определены следующие методы запросов которые клиент может использовать:
HEAD
GET
POST
LINK
UNLINK
PUT
DELETE
OPTIONS
TRACE
CONNECT (только https)
Нас интересуют GET и POST. Можно было бы еще обсудить и PUT но он достаточно редко используется. Если вас интересуют определения прочих методов перечисленных в списке, обратитесь к спецификации HTTP/1.1 (RFC 2068)
Что такое метод HTTP?
quote:
Метод - это команда HTTP, с которой начинается первая строка клиентского запроса. Метод сообщает серверу о цели клиентского запроса. Практически все серверы поддерживают методы HEAD GET POST. Поддержка остальных методов не всегда реализована. Названия методов регистрозависимые (get != GET)
В последних версиях PHP имеется несколько масивов (если track_vars On [в PHP 4.0.3 всегда On, вне зависимости от файла конфигурации]):
$_GET - переменные GET запроса
$_POST - переменные POST запроса
$_FILES - информация о файлах загружаемых методом HTTP POST
Вышеперечисленные имена - это более короткие имена стандартных массивов которые есть и в более ранних и текущей версиях PHP:
$HTTP_GET_VARS
$HTTP_POST_VARS
$HTTP_POST_FILES
Разницы между данными нет, разница только в имени с помощью которого можно получить доступ (т.е. $_GET['text'] === $HTTP_GET_VARS['text'])
Если директива register_globals установлена то доступ к переменным можно получить просто по имени без всяких ключей массива. Это не есть гуд, а признак плохого стиля - всегда выключайте register_globals (развернутое обсуждение этой директивы выходит за рамки описания темы)
Как определить метод запроса?
Напрямую:
PHP:
getenv('REQUEST_METHOD');
вернет [ HEAD | GET | POST| PUT] один из перечисленных.
Косвенным путем (не всегда и не все методы):
например: если есть QUERY_STRING(это не всегда правильно - строка запроса может отсутствовать при запросе методом GET) это метод GET, если есть CONTENT_LENGTH - это POST и т.д.
метод GET
Чтобы передать данные методом GET не надо создавать на HTML странице форму(использовать формы для запросов методом GET вам никто не запрещает - но это тупость) - достаточно ссылки на документ с добавлением строки запроса которая может выглядеть как переменная=значение пары объединяются с помощью амперсанда & а к URL страницы строка присоединяется с помощью вопросительного знака ?
Но можно не использовать пары ключ=значение если надо передать всего одну переменную для этого надо после знака вопроса написать ЗНАЧЕНИЕ(не имя) переменной. В сценарии доступ к этому значению выглядит так: PHP:
$my_var = getenv('QUERY_STRING');
при этом массив $_GET будет пустым
Преимущество передачи параметров таким способом заключается в том что клиенты которые не могут использовать метод POST (например поисковые машины) все же смогут просто пройдя по ссылке передать параметры скрипту и получить содержимое.
Недостаток в том, что просто изменив параметры в адресной строке пользователь может повернуть ход сценария непредсказуемым образом, это создает огромную дыру в безопасности в сочетании с неопределенными переменными и register_globals On или кто нибудь может узнать значение важной переменной(например ID сесии) просто посмотрев на экран монитора(или скриншот который сделан с помошью трояна )).
Для чего следует использовать:
- для доступа к общедоступным страницам с передачей параметров (повышение функциональности)
- передача информации не влияющей на уровень безопасности
Для чего не следует использовать
- для доступа к защищенным страницам с передачей параметров
- для передачи информации влияющей на уровень безопасности
- для передачи информации не подлежащей модифицированию пользователем (некоторые передают текст SQL запросов[что само по себе вопиющие нарушение правил ТБ] в БД с помощью этого метода =)
метод POST
Передать данные методом POST можно только с помощью формы на HTML странице. Основное отличие POST от GET в том что данные передаются не в заголовке запроса а в теле, следовательно пользователь их не видит. Модифицировать может только изменив саму форму - но в большинстве случаев такие запросы можно отвергнуть проверяя адрес страницы с которой были посланы данные, доступ к адресу: PHP:
getenv('HTTP_REFERER');
(о вопросах безопасности чуть позже)
Преимущество:
- большая безопасность и функциональность запросов с помощью форм методом POST
Недостаток:
- меньшая доступность
Для чего следует использовать:
- для передачи большого объема информации (текст, файлы..)
- для передачи любой важной информации
- для ограничения доступа (например использовать для навигации только форму - возможность доступная не всем программам-роботам или грабберам-контента)
Для чего не следует использовать:
- для затруднения юзабельности сайта =)
О структуре массива $_FILES
структура приблизительно следующая...
PHP:
$_FILES = array(
['имя поля формы'] array (
['name'] = 'имя файла у клиента без пути',
['type'] = 'тип содержимого MIME',
['tmp_name']
=
'временное имязагруженного файла на диске сервера',
['size'] = 'размер в байтах'
)
);
Еще о массивах
Существет так же массив $_REQUEST
В нем объединено содержимое массивов $_GET $_POST $_COOKIE (NOTES В ТЕМУ: я не проверял этот факт, но логично предположить что если в $_GET и $_COOKIE есть переменные с одинаковыми именами то в $_REQUEST они перезаписывают друг друга в соответствии с директивой конфигурации variables_order).
О безопасности связанной с приемом переменных извне
Я, при разработке web-приложений на PHP соблюдаю всего три правила ТБ (тб - сокр. от техника безопасности):
- не верить никому
- все проверять
- если невозможно проверить -> отказать в доступе или выполнить действие по умолчанию
Как априори(постоянная не требующая доказательств) считаю, что не существует нормальных пользователей, есть только злобные хацкеры, спаммеры, флудеры и хулиганы которых хлебом не корми, только дай напихать в форму всякой гадости типа HTML тегов или JavaScript, подделать REFERER и еще много всего нехорошего...
Проверка HTTP_REFERER не дает абсолютной защититы от изменения данных, потому что ее можно подделать. По ней можно лишь определить откуда пришел пользователь и не более того, но все же стоит ее проверять при приеме ЛЮБЫХ ЗАПРОСОВ МЕТОДОМ POST
Далее определите требования к данным которые вы получаете и проверьте их при приеме.
При проверке вы можете получить всего два значения:
- данные валидны
- данные не валидны
Если данные не валидны, надо принять решение, что делать дальше:
- ничего, просто теперь известно что данные неправильные
- привести данные в требуемый вид в сответствии с инструкцией
В теме Сказка про PHP скрипт описаны две функции:
set_valid и is_valid
is_valid - просто проверяет соответствуют ли данные набору правил, а set_valid исправляет данные если они не соответствуют набору правил(требованиям).
Наборы правил и действий по исправлению не заданы внутри функций и должны передаваться как параметры, это позволяет конструировать проверки любой сложности создавая свои функции и хранить все в одном месте не раскидывая по коду скрипта...
Напоследок...(для более продвинутых)
в одной из тем обсуждали с polo ошибку условия. Условие было истинным если переменная есть в куках ее не должно быть в GET или POST. Эта дискуссия навела меня на одну мысль в районе зачем нужны куки и данные запроса и как их разграничить. Возможно позже развернуто объясню свое мнение по этому вопросу.
Место где находиться переменаая, в $_GET или $_POST указывает лишь на метод, а $_COOKIE - это однозначно данные.
Нужно не заглядывать в массивы, проверяя значение переменной, а знать две вещи:
- было ли что то передано
- есть ли в нем то что нам надо
В соответствии с этим можем разделить запросы не зависимо от метода на две группы:
- запрос с передачей данных от клиента
- запрос без передачи данных
Как определить, отправил что нибудь клиент или нет - можно разобраться самому(примечание: то что метод запроса POST еще не говорит о том что там есть нужные нам данные), а заодно покидать все что он передал в свой массив или использовать $_REQUEST(но тогда не рекомендуется иметь переменные с одинаковыми именами в GET/POST и COOKIE - это сам по себе неверный подход, надо контролировать ситуацию и знать возможности клиента)
При приеме данных лишь определяем требование каким методом должны быть переданы (GET или POST) данные от клиента к серверу...
P.S.
Если после прочтения этого сообщения в ваших скриптах станет меньше хотя бы на одну ошибку, я могу считать что не зря возился с этим сообщением почти час =)
__________________
FAQ OFF
Сообщение было отредактировано SCHIZO 01-08-2002 в 21:59
Сообщить модератору об этом сообщении | Предупреждение | IP: определен
|
01-08-2002 21:50 |
|
|
Участник+
|
Полезная заметка. Думаю для начинающих должна много вопросов снять. |
[сооб. #18271]
01-08-2002 23:48 |
|
|
STFW
|
Это WD (work draft) вариант публикации из серии про PHP (пока она(серия публикаций)... |
[сооб. #18274]
02-08-2002 01:22 |
|
STFW


Зарегистрирован: Jul 2002
Место проживания: Кольский п-ов
Публикаций: 305
Статус:  |
Это WD (work draft) вариант публикации из серии про PHP (пока она(серия публикаций) ни как не называется, но мне нравится название "PHP in images" [ПХП в образах или ПХП в картинках], кому как нравиться).
Просто я сам сейчас для себя делаю кой какие выводы по поводу разработки скриптов, веб-приложений,веб-сервисов на PHP и считаю нужным поделиться с другими своими взглядами на проблему.
__________________
FAQ OFF
Сообщить модератору об этом сообщении | Предупреждение | IP: определен
|
02-08-2002 01:22 |
|
|
STFW


Зарегистрирован: Jul 2002
Место проживания: Кольский п-ов
Публикаций: 305
Статус:  |
[Для лучшего понимания вопроса, все же требуется внести ясность в отдельные детали.
В начале темы было сказано...
quote:
Чтобы передать данные методом GET не надо создавать на HTML странице форму(использовать формы для запросов методом GET вам никто не запрещает - но это тупость*) - достаточно ссылки на документ с добавлением строки запроса которая может выглядеть как переменная=значение...
*Под тупостью имеется ввиду использование такого способа когда он бесполезен или даже вреден.
Вот тут есть одна особенность, о которой обязательно следует упомянуть. А именно ...ссылка на документ с добавлением строки запроса...
Если вы сами создаете такую ссылку - то она статична и пользователь не может ее изменить. Единственный способ добавить полиморфность - заменить ее на форму для отправки которой используется метод GET и пользователь сам сможет ее формировать (но ваше приложение должно знать как обработать то, что отправит пользователь, а отправить он может все что угодно).
quote:
Именно так делается в поисковиках, (напр. Altavista) а в каталогах создаются статичные ссылки (напр. Yahoo).
Заключение
Не стоит совсем отказываться от метода GET в формах, надо его правильно использовать. Например для формирования значения параметра который должен ввести пользователь.
Метод GET в формах лучше использовать тогда, когда не требуется хранить данные формы на сервере, а использовать для этого запрос клиента.
С методом POST все наоборот: если что то требуется сохранить на стороне сервера, следует использовать именно этот метод.
Можно провести аналогию с правами доступа на чтение(GET) и запись(POST).
__________________
FAQ OFF
Сообщить модератору об этом сообщении | Предупреждение | IP: определен
|
09-08-2002 15:39 |
|
|
Shutdown -h now
|
[quote]всегда выключайте register_globals (развернутое обсуждение этой директивы... |
[сооб. #19712]
09-08-2002 22:01 |
|
Shutdown -h now


Зарегистрирован: Jul 2002
Место проживания: уже далеко от Moscow
Публикаций: 578
Статус:  |
quote: всегда выключайте register_globals (развернутое обсуждение этой директивы выходит за рамки описания темы)
Развернутому описанию может и не место, а краткому самое оно. Сказав "А" надо говорить "Б"...
В остальном статья на 5 баллов. 
Сообщить модератору об этом сообщении | Предупреждение | IP: определен
|
09-08-2002 22:01 |
|
|
Участник+
|
Господа, я хочу получить страницу с сервера по принципу использования fsockopen();
Но... |
[сооб. #47703]
07-07-2003 01:37 |
|
Участник+

Зарегистрирован: May 2002
Место проживания:
Публикаций: 50
Статус:  |
Господа, я хочу получить страницу с сервера по принципу использования fsockopen();
Но что-то не выходит, объясните в общих чертах (с примером) как можно получить хтмл код страницы с другого сервера. При этом если сервер - поддомен. т.ё. chto-to.gde-to.net
Буду вам благодарен.
Сообщить модератору об этом сообщении | Предупреждение | IP: определен
|
07-07-2003 01:37 |
|
|
Участник+
|
webgrs,
Почитай спецификацию HTTP. Или хотя бы вот эти две статьи про... |
[сооб. #47704]
07-07-2003 01:42 |
|
|
Формат времени GMT. Текущее время 21:48.
|
Правила форума:
Вы не можете создавать новые темы.
Вы не можете отвечать на существующие темы.
Вы не можете прикреплять файлы.
Вы не можете редактировать свои сообщения. |
HTML теги выкл.
Спец. код вкл.
Смайлики вкл.
[IMG] тег выкл.
|
|
|
|
| |
Page generated in 0.32870102 seconds (98.19% PHP - 1.81% MySQL) with 23 queries.
|
 |