Содержание
Использование pickle для сериализации данных
Pickle может оказаться более подходящим решением, особенно при необходимости сериализации объектов, не поддающихся конвертации в JSON, например объектов типа datetime:
Важный совет по безопасности: никогда не выгружайте данные с помощью pickle из источников, надежность которых вызывает у вас сомнения. Это может создать потенциальные риски безопасности.
Работа с различными браузерами и настройками
Если вы привыкли работать с Firefox, замените () на (). Для Selenium это различие не является существенным.
Работу с пользовательскими профилями в Chrome можно настроить через опции запуска:
Корректное завершение сеансов
Сеанс работы с драйвером следует завершать при помощи () для корректного закрытия всех процессов:
Синхронизация
Для задержки и предоставления странице времени на загрузку используйте ():
Сайты, подразумевающие посещение
Если сайт выставляет куки только после визита пользователя, сначала выполняется (), а затем добавляются куки:
Настройка бэкенда
Примеры для бэкенда сделаны при помощи Python и его фреймворка Flask. Если вы хотите воспроизводить код из данной статьи, создайте новую виртуальную среду Python и установите Flask.
В каталоге проекта создайте файл flask_app.py и используйте наши примеры для собственных экспериментов.
Несоответствующий хост (неправильный адрес хоста)
У браузеров нет другого выбора, кроме как отклонить данный кук. Chrome даже выдаст предупреждение (в отличии от Firefox):
Несоответствующий хост (поддомен)
Они находятся в одном домене, но поддомены отличаются. И снова браузер отклоняет такой кук:
Соответствующий хост (весь домен)
Здесь мы использовали Nginx, чтобы показать вам различные способы установки куков. Тот факт, что кук установлен сервером, а не кодом приложения, для браузера особой роли не играет. Важно то, из какого домена поступает кук.
Здесь браузер с радостью примет кук, потому что хост в Domain включает в себя хост, с которого пришел сам кук.
Кроме того, кук возвращается при любых новых запросах к, а также при любых запросах к поддоменам на.
Куки и список общедоступных суффиксов
Здесь кук поступает с, а атрибут Domain имеет значение. Что в такой ситуации нужно делать браузеру?
Вы можете подумать, что, так как входит в домен, браузер должен принять этот кук.
Но вместо этого он отклонит данный кук, поскольку тот поступает из домена, включенного в список общедоступных суффиксов.
Public Suffix List поддерживается Мозиллой и используется всеми браузерами для ограничения установки куков от имени других доменов.
- Общедоступный список суффиксов
- Куки и общедоступный список суффиксов
Работа с CORS
CORS — это аббревиатура от Cross-Origin Resource Sharing — «Совместное использование ресурсов между разными источниками». Это способ для серверов контролировать доступ к ресурсам в данном источнике, когда код JavaScript, работающий в другом источнике, запрашивает эти ресурсы.
По умолчанию браузеры блокируют запросы AJAX к удаленным ресурсам, которые не находятся в одном источнике, если только сервер не предоставляет определенный HTTP-заголовок с именем Access-Control-Allow-Origin.
Чтобы исправить предыдущую ошибку, нам нужно настроить CORS для Flask:
from flask import Flask, make_response, request, render_template, jsonify from flask_cors import CORS app = Flask(__name__) CORS(app=app) @(«/», methods=[«GET»]) def index(): return render_template(«») @(«/get-cookie/», methods=[«GET»]) def get_cookie(): response = make_response(«Here, take some cookie!») response.set_cookie(key=»id», value=»3db4adj3d») return response @(«/api/cities/», methods=[«GET»]) def cities(): if [«id»] == «3db4adj3d»: cities = [{«name»: «Rome», «id»: 1}, {«name»: «Siena», «id»: 2}] return jsonify(cities) return jsonify(msg=»Ops!»)
Теперь попробуйте еще раз нажать кнопку с открытой консолью браузера. В консоли вы должны увидеть следующее:
Несмотря на то, что мы получили ту же ошибку, на этот раз виноват второй маршрут.
К запросу не прикреплен кук с именем «id», поэтому Flask аварийно завершает работу и не устанавливает Access-Control-Allow-Origin.
В этом можно убедиться, посмотрев запрос во вкладке Network (в инструментах разработчика). Такие куки не отправляются:
Без этого флага Fetch просто игнорирует куки. Чтобы исправить наш пример, изменим код следующим образом:
const button = («button»); («click», function() { getACookie().then(() => getData()); }); function getACookie() { return fetch(«/», { credentials: «include» }).then(response => { // make sure to check in the real world! return («All good, fetch the data»); }); } function getData() { fetch(«/», { credentials: «include» }).then(response => { // make sure to check in the real world! return (); }).then(json => (json)); }
credentials: «include» должен присутствовать в первом Fetch-запросе, чтобы сохранить кук в хранилище.
Он также должен присутствовать во втором запросе, чтобы разрешить передачу куков обратно в серверную часть:
Чтобы разрешить передачу куков в запросах CORS, серверная часть также должна предоставить заголовок Access-Control-Allow-Credentials. Это легко поправить.
- credentials: «include» во фронтенде для Fetch-запроса
- Access-Control-Allow-Credentials и Access-Control-Allow-Origin в бэкенде.
Куки могут передаваться по запросам AJAX, но они должны соответствовать доменным правилам, которые мы здесь описали.
Конкретный пример
В нашем предыдущем примере использовался localhost, чтобы все было просто и воспроизводимо на вашем локальном компьютере.
Чтобы представить обмен куками по запросам AJAX в реальном мире, вы можете наметить себе следующий сценарий:
- Пользователь заходит на сайт.
- Он нажимает кнопку или выполняет какое-либо действие, которое запускает Fetch-запрос на.
- устанавливает кук с атрибутом Domain=.
- При последующих Fetch запросах на кук отправляется обратно.
Куки могут иметь своего рода секрет: атрибут Secure
Атрибут Secure для куков гарантирует, что куки никогда не будут приняты через HTTP. То есть браузер отклоняет куки с данным атрибутом, если соединение не происходит через HTTPS.
Чтобы пометить кук как безопасный, передайте в него соответствующий атрибут:
Если вы хотите попробовать это в реальной среде, выполните следующую команду в консоли и обратите внимание, как здесь curl не сохраняет куки через HTTP:
Примечание: это будет работать только в версии curl >=7.64.0, который реализует rfc6265bis. Более старые версии curl реализуют RCF6265.
Чтобы проверить куки в браузере, посетите обе версии указанного выше URL-адреса и проверьте хранилище куков в инструментах разработчика.
Не обманывайтесь самим словом Secure (безопасный). Куки придут к вам по безопасному соединению, но после того как они окажутся в вашем браузере, никакой защиты у них не будет.
По этой причине безопасный кук, как и любой другой, не предназначен для передачи конфиденциальных данных, даже если название предполагает обратное.
Не трогайте мои куки: атрибут HttpOnly
Атрибут HttpOnly для кука гарантирует, что этот самый кук недоступен для кода JavaScript. Это самая главная форма защиты против XSS атак.
Однако он отправляется при каждом последующем HTTP-запросе с учетом всех разрешений, установленных атрибутами Domain и Path.
Чтобы пометить кук как HttpOnly, установите данный атрибут следующим образом:
К куку, помеченному как HttpOnly, нельзя получить доступ из JavaScript. При проверке в консоли будет возвращать пустую строку.
Однако, если установить credentials обратно в состояние include, то при помощи Fetch-запроса можно будет опять отправлять и получать куки с атрибутом HttpOnly. Разумеется, при наличии разрешений от атрибутов Path и Domain.
Когда же лучше использовать атрибут HttpOnly? Всегда, когда это возможно. Куки всегда должны быть HttpOnly, за исключением случаев, когда есть особые требования для их отображения во время выполнения JavaScript.
Собственные и сторонние куки
Мы называем этот вид куков собственными. То есть, если я посещаю этот URL-адрес в браузере, и если я посещаю тот же URL-адрес или другую страницу на этом сайте (при условии, что атрибут Path установлен в значение /), то браузер отправляет куки обратно на сайт. Обычные куки, одним словом.
Теперь рассмотрим другую веб-страницу по адресу /. Эта страница также устанавливает куки и, кроме того, загружает изображение со стороннего ресурса, размещенное по адресу.
Этот сторонний ресурс, в свою очередь, сам устанавливает свои куки. Вы можете увидеть этот сценарий на скрине ниже:
Примечание: если вы используете Chrome 85, вы не увидите этот кук. Начиная с этой версии Chrome отклоняет его. Мы называем этот вид куков сторонними. Другой пример стороннего кука:
- Пользователь посещает страницу.
- Он нажимает кнопку или выполняет какое-либо действие, которое запускает Fetch-запрос на странице
- Теперь на странице хранится сторонний кук с.
Работа с атрибутом Samesite
На момент написания данной статьи сторонние куки вызывают всплывающее окно с предупреждением в консоли Chrome:
«Файл cookie, связанный с межсайтовым ресурсом /, был установлен без атрибута SameSite. Будущая версия Chrome будет доставлять файлы cookie с межсайтовыми запросами только в том случае, если они установлены с помощью SameSite=None и Secure.»
Браузер пытается нам сказать, что сторонние куки должны иметь новый атрибут SameSite. Но почему?
Атрибут SameSite — это новая функция, направленная на повышение безопасности куков. Она предназначена, чтобы предотвратить подделку межсайтовых запросов и избежать утечек конфиденциальности.
- Strict
- Lax
- None
Если мы являемся службой, предоставляющей встраиваемые виджеты (iframe), или нам необходимо размещать куки на удаленных веб-сайтах (по уважительной причине, а не для дикого отслеживания), эти куки должны быть помечены как SameSite=None и Secure:
В противном случае браузер отклонит сторонний кук. Вот что браузеры собираются делать в ближайшем будущем:
«Файл cookie, связанный с межсайтовым ресурсом /, был установлен без атрибута SameSite. Он был заблокирован, так как Chrome теперь доставляет файлы cookie только с межсайтовыми запросами, если для них установлено значение SameSite=None и Secure.»
Другими словами SameSite=None; Secure заставит сторонние куки работать так, как они работают сегодня, с той лишь разницей, что они должны передаваться только через HTTPS.
Настроенный таким образом кук отправляется вместе с каждым запросом, если домен и путь совпадают. Это нормальное поведение.
Стоит отметить, что атрибут SameSite относится не только к сторонним кукам.
По умолчанию браузеры будут применять SameSite=Lax для всех куков, как собственных, так и сторонних, если данный атрибут отсутствует. Вот какая политику у браузера Firefox Nightly относительно собственных куков:
«Кук get_frog_simplecookiename имеет атрибут SameSite, установленный в значение lax, потому что в нем отсутствовал атрибут SameSite, а SameSite=lax является значением по умолчанию для этого атрибута.»
Сторонние куки с атрибутом SameSite=Strict будут полностью отклоняться браузером.
Таблица №1
| Значение | Входящий кук | Выходящий кук |
| Strict | Отклонить | — |
| Lax | Принять | Отправить безопасным методом HTTP |
| None + Secure | Принять | Отправить |
Чтобы узнать больше о SameSite и подробно разобраться во всех вариантах использования этого атрибута, почитайте эти отличные ресурсы:
Куки и аутентификация
Аутентификация — одна из самых сложных задач в веб-разработке. Похоже, что вокруг этой темы так много путаницы, поскольку аутентификация на основе токенов с JWT, видимо, заменяет «старые» твердые шаблоны, такие как аутентификация на основе сессий.
Аутентификация на основе сессий
Аутентификация — один из наиболее распространенных случаев использования куков.
Когда вы посещаете сайт, запрашивающий аутентификацию, то при отправке учетных данных (например, через форму) бэкенд отправляет фронтенду заголовок Set-Cookie.
В этом заголовке Set-Cookie сервер может включать кук с именем session, session id или аналогичный.
Это единственный идентификатор, который браузер может видеть в открытом виде. Каждый раз, когда аутентифицированный пользователь запрашивает новую страницу в серверной части, браузер отправляет обратно кук сеанса.
На этом этапе, чтобы правильно идентифицировать пользователя, серверная часть связывает идентификатор сессии с самим сеансом, который находится в хранилище за кулисами.
Аутентификация на основе сессий представляет из себя отслеживание состояний, поскольку серверная часть должна отслеживать сессии для каждого пользователя. Хранилищем для этих сессий может быть:
- база данных
- хранилище ключей / значений, такое как Redis
- файловая система.
Из этих трех хранилищ сессий предпочтение следует отдавать Redis (или ему подобным).
Обратите внимание, что аутентификация на основе сессий не имеет ничего общего с хранилищем сессий браузера.
Она так называется (аутентификацией на основе сессий) только потому, что соответствующие данные для идентификации пользователя находятся в хранилище сессий бэкенда, что не то же самое, что хранилище сессий браузера.
Когда использовать аутентификацию на основе сессий?
Используйте ее всегда, когда это возможно. Аутентификация на основе сессий — одна из самых простых, безопасных и понятных форм аутентификации для сайтов. Она доступна по умолчанию во всех самых популярных веб-фреймворках, например в Django.
Но ее природа, связанная с отслеживанием состояния, также является и ее основным недостатком, особенно когда сайт обслуживается балансировщиком нагрузки. В этом случае могут помочь такие методы, как закрепление сессий или хранение сессий в централизованном хранилище Redis.
Замечание по поводу JWT
JWT (сокращение от JSON Web Tokens) — это механизм аутентификации, набирающий популярность в последние годы.
JWT хорошо подходит для одностраничных и мобильных приложений, но также создает и новый набор проблем. Типичный процесс для внешнего приложения, желающего пройти аутентификацию по API, следующий:
- Фронтенд отправляет учетные данные бэкенду.
- Бэкенд проверяет учетные данные и отправляет обратно токен.
- Фронтенд отправляет токен при каждом последующем запросе.
Главный вопрос, который возникает при таком подходе: где нам хранить этот токен во фронтенде, чтобы пользователь оставался авторизованным?
Самым естественным поступком для того, кто пишет на JavaScript, является сохранение токена в localStorage. Это плохо по многим причинам.
localStorage легко доступен из кода JavaScript и является легкой мишенью для XSS-атак.
Чтобы решить эту проблему, большинство разработчиков прибегают к сохранению токена JWT в куке, полагая, что HttpOnly и Secure могут защитить кук, по крайней мере, от XSS-атак.
Новый атрибут SameSite, установленный в состояние SameSite=Strict, также защитит ваш «кукинизированный» JWT от атак CSRF (Межсайтовая подделка запроса). Но это также полностью аннулирует вариант использования JWT во многих случаях, потому что SameSite = Strict не отправляет куки по запросам из разных источников!
Как насчет того, чтобы установить атрибут в состояние SameSite=Lax? Этот режим позволяет отправлять куки с помощью безопасных методов HTTP, а именно GET, HEAD, OPTIONS и TRACE. Запросы POST ни в коем случае не будут передавать куки.
На самом деле хранение токена JWT в куке или в localStorage — плохая идея.
Если вы действительно хотите использовать JWT вместо аутентификации на основе сессий, вы можете использовать JWT с обновляемыми токенами, чтобы пользователь все время оставался в системе.
Визуализация
**Сохранение состояния:** 📸🍪 Зафиксировать свои куки на снимке **Восстановление состояния:** 🔄🍪 Восстановить свои куки
Часто задаваемые вопросы о получении куки из браузера в Python
Вопрос: Как получить все куки для текущего сайта с помощью Selenium?
Ответ: Используйте driver.get_cookies(), который возвращает список словарей с данными куки.
Вопрос: Можно ли получить куки из браузера без использования Selenium?
Ответ: Да, можно использовать библиотеки browser-cookie3 или browsercookie для доступа к локальным файлам кук.
Вопрос: Как сохранить куки после закрытия браузера в Selenium?
Ответ: Сохраните результат driver.get_cookies() в файл с помощью pickle или json, а затем загрузите их при следующем запуске.
Вопрос: Как установить куки в браузере через Python?
Ответ: Используйте driver.add_cookie(cookie_dict) для установки куки в текущем сеансе.
Вопрос: Почему я не могу получить куки для определенного домена?
Ответ: Проверьте атрибуты Domain и Path куки, а также то, что вы находитесь на правильном URL.
Вопрос: Как работать с HttpOnly куками в Python?
Ответ: HttpOnly куки недоступны через JavaScript, но их можно получить через Selenium с помощью driver.get_cookies().
Вопрос: Как получить куки из Chrome с помощью Python?
Ответ: Используйте библиотеку browser-cookie3, указав путь к профилю Chrome, или Selenium с драйвером Chrome.
Вопрос: Что такое Secure атрибут куки и как он влияет на получение?
Ответ: Secure куки передаются только по HTTPS. При получении через Selenium они будут доступны, если вы работаете через защищенное соединение.
Вопрос: Как очистить все куки в браузере через Python?
Ответ: Используйте driver.delete_all_cookies() в Selenium для удаления всех кук текущего сеанса.
Вопрос: Как получить куки для конкретного URL?
Ответ: В Selenium используйте driver.get_cookies() после перехода на нужный URL, или отфильтруйте полученные куки по ключу ‘domain’.

























