Получение куки из браузера с помощью Python: сохранение, загрузка и аутентификация

0
68

Использование pickle для сериализации данных

Python and pickle module - serialize objects - изображение номер один
Python and pickle module — serialize objects — изображение номер один

Pickle может оказаться более подходящим решением, особенно при необходимости сериализации объектов, не поддающихся конвертации в JSON, например объектов типа datetime:

Важный совет по безопасности: никогда не выгружайте данные с помощью pickle из источников, надежность которых вызывает у вас сомнения. Это может создать потенциальные риски безопасности.

Работа с различными браузерами и настройками

Python print cookies - изображение номер два
Python print cookies — изображение номер два

Если вы привыкли работать с Firefox, замените () на (). Для Selenium это различие не является существенным.

Работу с пользовательскими профилями в Chrome можно настроить через опции запуска:

Корректное завершение сеансов

Python - изображение номер три
Python — изображение номер три

Сеанс работы с драйвером следует завершать при помощи () для корректного закрытия всех процессов:

Синхронизация

How to save and load cookies in - изображение номер четыре
How to save and load cookies in — изображение номер четыре

Для задержки и предоставления странице времени на загрузку используйте ():

Сайты, подразумевающие посещение

Working with - изображение номер пять
Working with — изображение номер пять

Если сайт выставляет куки только после визита пользователя, сначала выполняется (), а затем добавляются куки:

Настройка бэкенда

Session and - изображение номер шесть
Session and — изображение номер шесть

Примеры для бэкенда сделаны при помощи Python и его фреймворка Flask. Если вы хотите воспроизводить код из данной статьи, создайте новую виртуальную среду Python и установите Flask.

В каталоге проекта создайте файл flask_app.py и используйте наши примеры для собственных экспериментов.

Несоответствующий хост (неправильный адрес хоста)

Python requests not returning cookies - изображение номер семь
Python requests not returning cookies — изображение номер семь

У браузеров нет другого выбора, кроме как отклонить данный кук. Chrome даже выдаст предупреждение (в отличии от Firefox):

HTTP cookies на практике - изображение номер восемь
HTTP cookies на практике — изображение номер восемь

Несоответствующий хост (поддомен)

How to decode - изображение номер девять
How to decode — изображение номер девять

Они находятся в одном домене, но поддомены отличаются. И снова браузер отклоняет такой кук:

How to set - изображение номер десять
How to set — изображение номер десять

Соответствующий хост (весь домен)

Django - изображение номер одиннадцать
Django — изображение номер одиннадцать

Здесь мы использовали Nginx, чтобы показать вам различные способы установки куков. Тот факт, что кук установлен сервером, а не кодом приложения, для браузера особой роли не играет. Важно то, из какого домена поступает кук.

Здесь браузер с радостью примет кук, потому что хост в Domain включает в себя хост, с которого пришел сам кук.

Кроме того, кук возвращается при любых новых запросах к, а также при любых запросах к поддоменам на.

CGI: пишем простой сайт на - изображение номер двенадцать
CGI: пишем простой сайт на — изображение номер двенадцать

Куки и список общедоступных суффиксов

Всё о работе с cookie в - изображение номер тринадцать
Всё о работе с cookie в — изображение номер тринадцать

Здесь кук поступает с, а атрибут Domain имеет значение. Что в такой ситуации нужно делать браузеру?

Вы можете подумать, что, так как входит в домен, браузер должен принять этот кук.

Но вместо этого он отклонит данный кук, поскольку тот поступает из домена, включенного в список общедоступных суффиксов.

Public Suffix List поддерживается Мозиллой и используется всеми браузерами для ограничения установки куков от имени других доменов.

  • Общедоступный список суффиксов
  • Куки и общедоступный список суффиксов

Работа с CORS

Web - изображение номер четырнадцать
Web — изображение номер четырнадцать

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 (в инструментах разработчика). Такие куки не отправляются:

Python: cookies decryption problem - изображение номер пятнадцать
Python: cookies decryption problem — изображение номер пятнадцать

Без этого флага 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, но они должны соответствовать доменным правилам, которые мы здесь описали.

ЧИТАТЬ ТАКЖЕ:  Расчет P Value в Python: как посчитать и подогнать данные под теорию

Конкретный пример

Localhost,Download and install in your computer - изображение номер шестнадцать
Localhost,Download and install in your computer — изображение номер шестнадцать

В нашем предыдущем примере использовался localhost, чтобы все было просто и воспроизводимо на вашем локальном компьютере.

Чтобы представить обмен куками по запросам AJAX в реальном мире, вы можете наметить себе следующий сценарий:

  1. Пользователь заходит на сайт.
  2. Он нажимает кнопку или выполняет какое-либо действие, которое запускает Fetch-запрос на.
  3. устанавливает кук с атрибутом Domain=.
  4. При последующих Fetch запросах на кук отправляется обратно.

Куки могут иметь своего рода секрет: атрибут Secure

Handle - изображение номер семнадцать
Handle — изображение номер семнадцать

Атрибут Secure для куков гарантирует, что куки никогда не будут приняты через HTTP. То есть браузер отклоняет куки с данным атрибутом, если соединение не происходит через HTTPS.

Чтобы пометить кук как безопасный, передайте в него соответствующий атрибут:

Если вы хотите попробовать это в реальной среде, выполните следующую команду в консоли и обратите внимание, как здесь curl не сохраняет куки через HTTP:

Примечание: это будет работать только в версии curl >=7.64.0, который реализует rfc6265bis. Более старые версии curl реализуют RCF6265.

Чтобы проверить куки в браузере, посетите обе версии указанного выше URL-адреса и проверьте хранилище куков в инструментах разработчика.

Не обманывайтесь самим словом Secure (безопасный). Куки придут к вам по безопасному соединению, но после того как они окажутся в вашем браузере, никакой защиты у них не будет.

По этой причине безопасный кук, как и любой другой, не предназначен для передачи конфиденциальных данных, даже если название предполагает обратное.

Не трогайте мои куки: атрибут HttpOnly

Cookie-файлы: что это, как включить, настроить, очистить и защитить куки в - изображение номер восемнадцать
Cookie-файлы: что это, как включить, настроить, очистить и защитить куки в — изображение номер восемнадцать

Атрибут HttpOnly для кука гарантирует, что этот самый кук недоступен для кода JavaScript. Это самая главная форма защиты против XSS атак.

Однако он отправляется при каждом последующем HTTP-запросе с учетом всех разрешений, установленных атрибутами Domain и Path.

Чтобы пометить кук как HttpOnly, установите данный атрибут следующим образом:

К куку, помеченному как HttpOnly, нельзя получить доступ из JavaScript. При проверке в консоли будет возвращать пустую строку.

Однако, если установить credentials обратно в состояние include, то при помощи Fetch-запроса можно будет опять отправлять и получать куки с атрибутом HttpOnly. Разумеется, при наличии разрешений от атрибутов Path и Domain.

Когда же лучше использовать атрибут HttpOnly? Всегда, когда это возможно. Куки всегда должны быть HttpOnly, за исключением случаев, когда есть особые требования для их отображения во время выполнения JavaScript.

Собственные и сторонние куки

Install - изображение номер девятнадцать
Install — изображение номер девятнадцать

Мы называем этот вид куков собственными. То есть, если я посещаю этот URL-адрес в браузере, и если я посещаю тот же URL-адрес или другую страницу на этом сайте (при условии, что атрибут Path установлен в значение /), то браузер отправляет куки обратно на сайт. Обычные куки, одним словом.

Теперь рассмотрим другую веб-страницу по адресу /. Эта страница также устанавливает куки и, кроме того, загружает изображение со стороннего ресурса, размещенное по адресу.

Этот сторонний ресурс, в свою очередь, сам устанавливает свои куки. Вы можете увидеть этот сценарий на скрине ниже:

Куки - что это такое и для чего нужны файлы cookie - как почистить и какую инфор - изображение номер двадцать
Куки — что это такое и для чего нужны файлы cookie — как почистить и какую инфор — изображение номер двадцать

Примечание: если вы используете Chrome 85, вы не увидите этот кук. Начиная с этой версии Chrome отклоняет его. Мы называем этот вид куков сторонними. Другой пример стороннего кука:

  1. Пользователь посещает страницу.
  2. Он нажимает кнопку или выполняет какое-либо действие, которое запускает Fetch-запрос на странице
  3. Теперь на странице хранится сторонний кук с.

Работа с атрибутом Samesite

Schemeful - изображение номер двадцать один
Schemeful — изображение номер двадцать один

На момент написания данной статьи сторонние куки вызывают всплывающее окно с предупреждением в консоли 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 является значением по умолчанию для этого атрибута.»

ЧИТАТЬ ТАКЖЕ:  Количество делителей натурального числа: функция на Python с примерами кода

Сторонние куки с атрибутом SameSite=Strict будут полностью отклоняться браузером.

Таблица №1

Значение Входящий кук Выходящий кук
Strict Отклонить —
Lax Принять Отправить безопасным методом HTTP
None + Secure Принять Отправить

Чтобы узнать больше о SameSite и подробно разобраться во всех вариантах использования этого атрибута, почитайте эти отличные ресурсы:

Куки и аутентификация

Использование - изображение номер двадцать два
Использование — изображение номер двадцать два

Аутентификация — одна из самых сложных задач в веб-разработке. Похоже, что вокруг этой темы так много путаницы, поскольку аутентификация на основе токенов с JWT, видимо, заменяет «старые» твердые шаблоны, такие как аутентификация на основе сессий.

Аутентификация на основе сессий

HTTP - изображение номер двадцать три
HTTP — изображение номер двадцать три

Аутентификация — один из наиболее распространенных случаев использования куков.

Когда вы посещаете сайт, запрашивающий аутентификацию, то при отправке учетных данных (например, через форму) бэкенд отправляет фронтенду заголовок Set-Cookie.

В этом заголовке Set-Cookie сервер может включать кук с именем session, session id или аналогичный.

Это единственный идентификатор, который браузер может видеть в открытом виде. Каждый раз, когда аутентифицированный пользователь запрашивает новую страницу в серверной части, браузер отправляет обратно кук сеанса.

На этом этапе, чтобы правильно идентифицировать пользователя, серверная часть связывает идентификатор сессии с самим сеансом, который находится в хранилище за кулисами.

Аутентификация на основе сессий представляет из себя отслеживание состояний, поскольку серверная часть должна отслеживать сессии для каждого пользователя. Хранилищем для этих сессий может быть:

  • база данных
  • хранилище ключей / значений, такое как Redis
  • файловая система.

Из этих трех хранилищ сессий предпочтение следует отдавать Redis (или ему подобным).

Обратите внимание, что аутентификация на основе сессий не имеет ничего общего с хранилищем сессий браузера.

Она так называется (аутентификацией на основе сессий) только потому, что соответствующие данные для идентификации пользователя находятся в хранилище сессий бэкенда, что не то же самое, что хранилище сессий браузера.

Когда использовать аутентификацию на основе сессий?

html - изображение номер двадцать четыре
html — изображение номер двадцать четыре

Используйте ее всегда, когда это возможно. Аутентификация на основе сессий — одна из самых простых, безопасных и понятных форм аутентификации для сайтов. Она доступна по умолчанию во всех самых популярных веб-фреймворках, например в Django.

Но ее природа, связанная с отслеживанием состояния, также является и ее основным недостатком, особенно когда сайт обслуживается балансировщиком нагрузки. В этом случае могут помочь такие методы, как закрепление сессий или хранение сессий в централизованном хранилище Redis.

Замечание по поводу JWT

How to - изображение номер двадцать пять
How to — изображение номер двадцать пять

JWT (сокращение от JSON Web Tokens) — это механизм аутентификации, набирающий популярность в последние годы.

JWT хорошо подходит для одностраничных и мобильных приложений, но также создает и новый набор проблем. Типичный процесс для внешнего приложения, желающего пройти аутентификацию по API, следующий:

  1. Фронтенд отправляет учетные данные бэкенду.
  2. Бэкенд проверяет учетные данные и отправляет обратно токен.
  3. Фронтенд отправляет токен при каждом последующем запросе.

Главный вопрос, который возникает при таком подходе: где нам хранить этот токен во фронтенде, чтобы пользователь оставался авторизованным?

Самым естественным поступком для того, кто пишет на 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’.