Данная глава временно взята из первой версии книги и подлежит корректировке. Вы можете помочь с этим!
Перевод © Попов Руслан <radz • yandex • ru>
Пришло время для исповеди: до этого момента мы умышленно игнорировали очень важный аспект разработки.
До сих пор мы рассматривали общий случай создания HTML, но в этой главе мы пойдём другим путём и рассмотрим возможности Django для генерации других видов контента. До этого момента мы рассматривали посетителей нашего сайта как безликую, анонимную массу просматривающую наши аккуратно свёрстанные страницы.
Конечно, на самом деле всё не так. За браузерами, которые работают с нашим сайтом, сидят реальные люди (по крайней мере, иногда). Это нельзя игнорировать. Интернет предназначен для объединения людей, а не машин. Если мы стараемся разрабатывать совершенно неотразимые сайты, в конечном счёте нам придётся учитывать мнение людей.
К сожалению, не всё так просто. HTTP разработан так, чтобы не учитывать состояния. Таким образом, каждый запрос происходит как-бы в вакууме. Не существует взаимосвязи между одним запросом и другим. Соответственно, мы никак не сможем привязаться к какому-нибудь аспекту (IP адрес, тип браузера и так далее) для гарантированного определения запросов от одного конкретного пользователя.
В этой главе вы научитесь как решать подобную задачу. Мы начнём с нижнего уровня (cookies) и продолжим изучение инструментов высокого уровня для поддержки сессий, аутентификации и авторизации пользователей.
Разработчики браузеров давно поняли, что отсутствие поддержки состояний в протоколе HTTP вызвало большие трудности у веб разработчиков. И тогда были созданы cookie. Cookie — это небольшие кусочки информации, которые браузер сохраняет по просьбе веб сервера. При каждом обращении браузера к странице определённого сайта, он отсылает полученную ранее cookie.
Давайте рассмотрим как это работает. Когда вы открываете свой браузер и переходите на http://google.com/, ваш браузер отправляет HTTP запрос на Google, который начинается так:
GET / HTTP/1.1
Host: google.com
...
Ответ Google выглядит обычно так:
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;
expires=Sun, 17-Jan-2038 19:14:07 GMT;
path=/; domain=.google.com
Server: GWS/2.1
...
Обратите внимание на заголовок Set-Cookie. Ваш браузер сохранит значение cookie (PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671) и будет отсылать его обратно, при каждом обращении к серверу Google. Таким образом, при следующем посещении Google, ваш браузер будет посылать такой запрос:
GET / HTTP/1.1
Host: google.com
Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671
...
Google затем может использовать значение Cookie для определение того, что вы именно тот, кто обращался к сайту ранее. Значение, например, может быть ключом записи в базе данных, которая хранит информацию о пользователе. Google может (и будет) использовать её для отображения вашего имени на странице.
Для сохранения состояний в Django большую часть времени вы пожелаете использовать высокоуровневые сессии и/или среду пользователя, которая будет рассмотрена в этой главе чуть позже. Однако, мы прервёмся и посмотрим как читать и писать cookie на низком уровне. Это поможет вам понять как работают инструменты, которые описаны далее. И это вам пригодится, если вам придётся напрямую работать с cookie для решения своих задач.
Прочитать уже установленный cookie невероятно просто. Каждый объект запроса обладает объектом COOKIES, который выглядит как словарь. Вы можете использовать его для чтения значения любого cookie, которые браузер отправил в представление:
def show_color(request):
if "favorite_color" in request.COOKIES:
return HttpResponse("Your favorite color is %s" % \
request.COOKIES["favorite_color"])
else:
return HttpResponse("You don't have a favorite color.")
Записать cookie гораздо сложнее. Вам потребуется использовать
метод set_cookie()
объекта
HttpResponse
. Ниже приведён пример
установки cookie favorite_color, значение для
которого берётся из параметра GET:
def set_color(request):
if "favorite_color" in request.GET:
# Create an HttpResponse object...
response = HttpResponse("Your favorite color is now %s" % \
request.GET["favorite_color"])
# ... and set a cookie on the response
response.set_cookie("favorite_color",
request.GET["favorite_color"])
return response
else:
return HttpResponse("You didn't give a favorite color.")
Вы также можете передать ряд необязательных аргументов в
response.set_cookie()
, которые управляют
поведением cookie, подробности описаны в таблице «Опции cookie»:
Таблица 12.1. Опции cookie
Параметр | По умолчанию | Описание |
---|---|---|
max_age | None | Время (в секундах) активности cookie. Если данный параметр имеет значение None, то cookie действует до закрытия браузера. |
expires | None | Точная дата и время окончания действия cookie. Должна быть указана в формате Wdy, DD-Mth-YY HH:MM:SS GMT. Если этот параметр установлен, он имеет преимущество над max_age. |
path | / |
Префикс пути для которого верен данный cookie. Браузеры отправляют cookie на сервер, только для страниц соответствующих указанному префиксу пути. Таким образом вы можете использовать этот параметр для отправления cookie в определённую секцию сайта. Этот параметр очень полезен в случае, когда вы не контролируете высший уровень домена вашего сайта. |
domain | None |
Домен для которого действителен cookie. Вы можете использовать этот параметр для установке cookie для другого домена. Например, domain=".example.com" установит cookie, который будет отправляться страницам доменов www.example.com, www2.example.com и an.other.sub.domain.example.com. Если этот параметр установлен в None, то cookie будет доступен только для установившего его домена. |
secure | False | Если параметр установлен в True, то браузер передаёт этот cookie на сервер по протоколу HTTPS. |
Вы могли отметить ряд потенциальных проблем методики работы с cookie. Взглянем на наиболее важные из них:
Хранение cookie является исключительно добровольным. Браузеры ничего не гарантируют. В действительности все браузеры позволяют пользователям управлять политикой работы с cookie. Если вы желаете увидеть как важны cookie для веба, включите опцию браузера «Спрашивать разрешение для каждого cookie».
Несмотря на их почти универсальное использование, cookie ненадёжны. Это означает, что разработчики должны проверять, что пользователь действительно принял cookie прежде чем начинать использовать их.
Самое главное, никогда не сохраняйте важную информацию в cookie. Интернет заполнен ужасными историями о разработчиках, которые сохраняли не восстанавливаемую информацию в cookie.
Cookie небезопасны, особенно те, которые отправлялись без использования протокола HTTPS. Cookie крайне легко прочитать, по причине того, что они пересылают информацию чистым текстом. Таким образом, атакующий прослушивает канал, ловит cookie и читает информацию. Это означает, что вы никогда не будете пересылать важную информацию в cookie.
Существует более хитрая атака, известная как человек посередине, когда атакующий перехватывает cookie и использует его, чтобы представиться вами. Глава 19 FIXME подробно описывает такие атаки и методы их предотвращения.
Cookie не защищены даже от того, кому они отсылаются. Большинство браузеров предоставляют простые способы изменения содержимого отдельных cookie, а изобретательные пользователи могут всегда воспользоваться такими инструментами, как mechanize для ручного создания HTTP запросов.
Таким образом, вы не можете хранить в cookie данные, которые могут быть чувствительны к взлому. Стандартная ошибка при работе с cookie — хранение чего-нибудь такого IsLogged=1 в cookie после авторизации пользователя. Вы удивились бы количеству сайтов в которых используется такой механизм при авторизации пользователей. Нужна только секунда для взлома таких «защищённых» сайтов.
4 комментария | Оставьте комментарий
У вас тут заместо FIXME
FIMXE =)
А у вас есть возможность это исправить через GitHub :)
А как через туда исправить ? о_0
Форкнуть репозиторий с книгой, внести правки, нажать на кнопку Pull Request.