HTTP Протокол
О, это обязательный раздел для всех web-разработчиков, я прям настаиваю на изучении данного материала для всех-всех-всех.
HTTP (HyperText Transfer Protocol) — это «протокол передачи гипертекста», т.е. по сути своей это текстовый протокол, и его понять не составит труда.
Изначально подразумевали, что по этому протоколу будет только HTML передаваться, отсель и название, а сейчас чего только не отправляют и =(^.^)= и(•ㅅ•)
Чтобы не ходить вокруг да около, давайте я вам приведу пример общения по HTTP протоколу.
Вот пример запроса, каким его отправляет ваш браузер, когда вы запрашиваете страницу http://example.com
:
GET / HTTP/1.1
Host: example.com
Accept: text/html
А вот пример ответа:
HTTP/1.1 200 OK
Content-Length: 1983
Content-Type: text/html; charset=utf-8
<html>
<head>...</head>
<body>...</body>
</html>
Это очень упрощенные примеры, но и тут можно увидеть из чего состоят HTTP запрос и ответ:
- стартовая строка — для запроса содержит метод и путь запрашиваемой страницы, для ответа - версию протокола и код ответа
- заголовки — имеют формат ключ-значение разделенные двоеточием, каждый новый заголовок пишется с новой строки
- тело сообщения — непосредственно HTML либо данные отделяют от заголовков двумя переносами строки, могут отсутствовать, как в приведенном запросе
Так, вроде с протоколом разобрались - он простой, ведёт свою историю аж с 1992-го года, так что идеальным его не назовешь, но какой есть - отправили запрос - получите ответ, и всё, сервер и клиент никоим образом более не связаны. Но подобный сценарий отнюдь не единственный возможный, у нас же может быть авторизация, сервер должен каким-то образом понимать, что вот этот запрос пришёл от определенного пользователя, т.е. клиент и сервер должны общаться в рамках некой сессии. И да, для этого придумали следующий механизм:
- При авторизации пользователя, сервер генерирует и запоминает уникальный ключ - идентификатор сессии, и сообщает его браузеру
- Браузер сохраняет этот ключ, и при каждом последующем запросе, его отправляет
Для реализации этого механизма и были созданы cookie (куки, печеньки) — простые текстовые файлы на вашем компьютере, по файлу для каждого домена (хотя некоторые браузеры более продвинутые, и используют для хранения SQLite базу данных), при этом браузер накладывает ограничение на количество записей и размер хранимых данных (для большинства браузеров это 4096 байт, см. RFC 2109 от 1997-го года)
Т.е. если украсть cookie из вашего браузера, то можно будет зайти на вашу страничку в facebook от вашего имени? Не пугайтесь, так сделать нельзя, по крайней мере с facebook, и дальше я вам покажу один из возможных способов защиты от данного вида атаки на ваших пользователей.
Давайте теперь посмотрим как изменятся наши запрос-ответ, будь там авторизация:
Request
POST /login/ HTTP/1.1
Host: example.com
Accept: text/html
login=Username&password=Userpass
Метод у нас изменился на POST, и в теле запроса у нас передаются логин и пароль. Если использовать метод GET, то строка
запроса будет содержать логин и пароль, что не очень правильно с идеологической точки зрения, и имеет ряд побочных явлений
в виде логирования (например, в том же access.log
) и кеширования паролей в открытом виде.
Response
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: KEY=VerySecretUniqueKey
<html>
<head>...</head>
<body>...</body>
</html>
Ответ сервер будет содержать заголовок Set-Cookie: KEY=VerySecretUniqueKey
, что заставит браузер сохранить
эти данные в файлы cookie, и при следующем обращении к серверу - они будут отправлены и опознаны сервером:
Request
GET / HTTP/1.1
Host: example.com
Accept: text/html
Cookie: KEY=VerySecretUniqueKey
Как можно заметить, заголовки отправляемые браузером (Request Headers) и сервером (Response Headers) отличаются, хотя есть и общие и для запросов и для ответов (General Headers)
Сервер узнал нашего пользователя по присланным cookie, и дальше предоставит ему доступ к личной информации. Так что, с сессиями в HTTP разобрались? Идём дальше.
Эка я RFC в сотни страниц влепил в одну страничку, так же многое можно пропустить... Это да, если есть желание посмотрите на RFC2616, но пока можете не забивать этим голову.