Как правильно отправить POST запрос с CSRF токеном для Laravel?

Ссылка скопирована
PHP
1 ответ

Добрый день. Пытаюсь отправить POST запрос на другой сайт, через cURL. Адрес https://promokod.pikabu.ru/coupon/5ka/Lty7boqhMLLy хочу получить ответ в котором есть json, оттуда вытащить ключ promocode.

Предполагаю, что требуется для начала получить CSRF token. Захожу на страницу и получаю этот токен, пытаюсь отправить, но в ответ получаю ошибку { "message": "CSRF token mismatch." }. Насколько я понимаю, данный сайт сделан на Laravel.

Делаю так:

<?php // Инициализация cURL-сессии для GET-запроса страницы и извлечения CSRF-токена $ch = curl_init();  // Установка параметров cURL-сессии для GET-запроса curl_setopt($ch, CURLOPT_URL, 'https://promokod.pikabu.ru/shops/5ka'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');  // Выполнение GET-запроса $response = curl_exec($ch);  // Закрытие cURL-сессии curl_close($ch);  // Парсинг страницы для извлечения CSRF-токена preg_match('/<meta name="csrf-token" content="(.+?)">/', $response, $matches); if (isset($matches[1])) {     $csrf_token = $matches[1]; } else {     die("CSRF-токен не найден"); }  // Заголовки для POST-запроса $headers = [     "Accept: application/json, text/plain, */*",     "Accept-Encoding: gzip, deflate, br",     "Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",     "Connection: keep-alive",     "Content-Length: 2",     "Content-Type: application/json;charset=UTF-8",     "Cookie: pcid=4yDnaZt3zv2; ...",     "DNT: 1",     "Host: promokod.pikabu.ru",     "Origin: https://promokod.pikabu.ru",     "Referer: https://promokod.pikabu.ru/shops/5ka",     "Sec-Fetch-Dest: empty",     "Sec-Fetch-Mode: cors",     "Sec-Fetch-Site: same-origin",     "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",     "X-Requested-With: XMLHttpRequest",     "X-XSRF-TOKEN: " . $csrf_token ];  // Инициализация cURL-сессии для POST-запроса $ch = curl_init();  // Установка параметров cURL-сессии для POST-запроса curl_setopt($ch, CURLOPT_URL, 'https://promokod.pikabu.ru/coupon/5ka/Lty7boqhMLLy'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([])); // Данные запроса (пустой JSON в данном случае)  // Выполнение POST-запроса $response = curl_exec($ch);  // Закрытие cURL-сессии curl_close($ch);  // Обработка ответа от сервера echo $response; ?>

<?php // Инициализация cURL-сессии для GET-запроса страницы и извлечения CSRF-токена $ch = curl_init(); // Установка параметров cURL-сессии для GET-запроса curl_setopt($ch, CURLOPT_URL, 'https://promokod.pikabu.ru/shops/5ka'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); // Выполнение GET-запроса $response = curl_exec($ch); // Закрытие cURL-сессии curl_close($ch); // Парсинг страницы для извлечения CSRF-токена preg_match('/<meta name="csrf-token" content="(.+?)">/', $response, $matches); if (isset($matches[1])) { $csrf_token = $matches[1]; } else { die("CSRF-токен не найден"); } // Заголовки для POST-запроса $headers = [ "Accept: application/json, text/plain, */*", "Accept-Encoding: gzip, deflate, br", "Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7", "Connection: keep-alive", "Content-Length: 2", "Content-Type: application/json;charset=UTF-8", "Cookie: pcid=4yDnaZt3zv2; ...", "DNT: 1", "Host: promokod.pikabu.ru", "Origin: https://promokod.pikabu.ru", "Referer: https://promokod.pikabu.ru/shops/5ka", "Sec-Fetch-Dest: empty", "Sec-Fetch-Mode: cors", "Sec-Fetch-Site: same-origin", "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36", "X-Requested-With: XMLHttpRequest", "X-XSRF-TOKEN: " . $csrf_token ]; // Инициализация cURL-сессии для POST-запроса $ch = curl_init(); // Установка параметров cURL-сессии для POST-запроса curl_setopt($ch, CURLOPT_URL, 'https://promokod.pikabu.ru/coupon/5ka/Lty7boqhMLLy'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([])); // Данные запроса (пустой JSON в данном случае) // Выполнение POST-запроса $response = curl_exec($ch); // Закрытие cURL-сессии curl_close($ch); // Обработка ответа от сервера echo $response; ?>

Заголовки запроса, которые посылает браузер:

Как правильно отправить POST запрос с CSRF токеном для Laravel?

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

Дополнительно:

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

  • 1. Причём тут Laravel?
    2. Когда вы уже забудете про curl?
  • JhaoDa, какая альтернатива cURL, если использовать PHP ?
  • Александр Андропов, в документации ларвел есть ответ — и для ларавел, и для чистого РНР.
  • Сергей delphinpro, сделал всё в одной сессии, но результат тот же
  • Александр Андропов, как определили? Если что я говорил о http сессии, а не об инстансе курла.
  • Сергей delphinpro, тогда видимо понял не правильно. Можете пожалуйста показать пример ?
  • Александр Андропов, для посетителя бэкэндом создается сессия. Ее идентификатор сохраняется в куках и с каждым следующим запросом прилетает из браузера на сервер. По этому идентификатору бэкэнд узнает, что зашел тот же самый посетитель, для которого уже открыта сессия, в которой лежит валидный csrf токен.
    Я выше написал - вам нужно сохранять куки между запросами. Для хранения печенек у курла есть специальная настройка. Собственно весь пример будет заключаться в написании этой опции (там их кстати две.Я хз какая реально нужна и для чего они различаются, указываю обе).
  • Александр Андропов, альтернатива минимально это guzzle, в laravel можно их обёртку использовать над guzzle - laravel http client
  • Ответы:

    csrf-token из html не используется
    смотрите cookies которые присылает сервер при GET-запросе к https://promokod.pikabu.ru/shops/5ka
    в заголовках приходит Set-Cookie: XSRF-TOKEN=

    curl -L -I "https://promokod.pikabu.ru/shops/5ka" HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding Cache-Control: no-cache, private Date: Fri, 06 Oct 2023 12:56:29 GMT X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 Set-Cookie: XSRF-TOKEN=eyJpdiI6ImZuTllpTWRIb2ZDalF5.......TkyOWY3In0%3D; expires=Fri, 13-Oct-2023 12:56:29 GMT; Max-Age=604800; path=/

    curl -L -I "https://promokod.pikabu.ru/shops/5ka" HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding Cache-Control: no-cache, private Date: Fri, 06 Oct 2023 12:56:29 GMT X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 Set-Cookie: XSRF-TOKEN=eyJpdiI6ImZuTllpTWRIb2ZDalF5.......TkyOWY3In0%3D; expires=Fri, 13-Oct-2023 12:56:29 GMT; Max-Age=604800; path=/

    Это значение и надо использовать для дальнейшего POST-запроса

    • Сейчас я делаю так:
      $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36';  // Используем cURL для создания сессии $ch = curl_init();  // Устанавливаем параметры для GET-запроса curl_setopt_array($ch, array(     CURLOPT_URL => 'https://promokod.pikabu.ru/shops/5ka',     CURLOPT_RETURNTRANSFER => true,     CURLOPT_HEADER => true,     CURLOPT_USERAGENT => $userAgent, ));  // Выполняем GET-запрос $response = curl_exec($ch);  // Парсим заголовки ответа, чтобы найти и сохранить cookie preg_match('/Set-Cookie:s*(XSRF-TOKEN=[^;]+)/', $response, $matches); $cookieXSRF = isset($matches[1]) ? $matches[1] : ''; preg_match('/Set-Cookie:s*(laravel_session=[^;]+)/', $response, $matches); $cookieLaravelSession = isset($matches[1]) ? $matches[1] : '';  if (empty($cookieXSRF) || empty($cookieLaravelSession)) {     die("Не удалось получить XSRF-TOKEN и/или laravel_session cookies."); }  // Имитируем пустой JSON-запрос $jsonData = json_encode([]);  // Устанавливаем параметры для POST-запроса curl_setopt_array($ch, array(     CURLOPT_URL => 'https://promokod.pikabu.ru/coupon/5ka/Lty7boqhMLLy',     CURLOPT_POST => true,     CURLOPT_RETURNTRANSFER => true,     CURLOPT_HTTPHEADER => array(         'Cookie: ' . $cookieXSRF . '; ' . $cookieLaravelSession, // Передаем оба cookie         'User-Agent: ' . $userAgent, // Устанавливаем User-Agent             ),     CURLOPT_POSTFIELDS => $jsonData, // Передаем пустой JSON-запрос ));  // Выполняем POST-запрос $response = curl_exec($ch);  // Проверяем наличие ошибок if ($response === false) {     die('Ошибка cURL: ' . curl_error($ch)); }  // Закрываем соединение cURL curl_close($ch);  // Выводим ответ на экран echo $response;

      $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'; // Используем cURL для создания сессии $ch = curl_init(); // Устанавливаем параметры для GET-запроса curl_setopt_array($ch, array( CURLOPT_URL => 'https://promokod.pikabu.ru/shops/5ka', CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_USERAGENT => $userAgent, )); // Выполняем GET-запрос $response = curl_exec($ch); // Парсим заголовки ответа, чтобы найти и сохранить cookie preg_match('/Set-Cookie:s*(XSRF-TOKEN=[^;]+)/', $response, $matches); $cookieXSRF = isset($matches[1]) ? $matches[1] : ''; preg_match('/Set-Cookie:s*(laravel_session=[^;]+)/', $response, $matches); $cookieLaravelSession = isset($matches[1]) ? $matches[1] : ''; if (empty($cookieXSRF) || empty($cookieLaravelSession)) { die("Не удалось получить XSRF-TOKEN и/или laravel_session cookies."); } // Имитируем пустой JSON-запрос $jsonData = json_encode([]); // Устанавливаем параметры для POST-запроса curl_setopt_array($ch, array( CURLOPT_URL => 'https://promokod.pikabu.ru/coupon/5ka/Lty7boqhMLLy', CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Cookie: ' . $cookieXSRF . '; ' . $cookieLaravelSession, // Передаем оба cookie 'User-Agent: ' . $userAgent, // Устанавливаем User-Agent ), CURLOPT_POSTFIELDS => $jsonData, // Передаем пустой JSON-запрос )); // Выполняем POST-запрос $response = curl_exec($ch); // Проверяем наличие ошибок if ($response === false) { die('Ошибка cURL: ' . curl_error($ch)); } // Закрываем соединение cURL curl_close($ch); // Выводим ответ на экран echo $response;

      и получаю 419 Page Expired

      Как правильно отправить POST запрос с CSRF токеном для Laravel?

    • Александр Андропов, добавьте CURLOPT_VERBOSE=>true и посмотрите что у вас вообще на сервер улетает
    • Дмитрий, странно, что при добавлении этой опции вообще ничего не произошло. Экран такой же как на скрине выше.
    • Ну либо я с названием опции ошибся, либо вы не туда вставили
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Андрей PHP Ответ

    Для отправки POST запроса с CSRF токеном в Laravel, вам необходимо включить CSRF защиту в вашем приложении и передать токен вместе с запросом.

    Прежде всего, убедитесь, что в вашем шаблоне Blade формы добавлен токен CSRF с помощью директивы @csrf:

     
        @csrf
        <!-- Остальные поля формы -->

    @csrf <!-- Остальные поля формы -->

    Затем, в JavaScript коде (или в другом месте, где вы отправляете запрос) вы можете получить значение CSRF токена из мета-тега в вашем HTML коде и добавить его к вашему POST запросу. Например, если вы используете jQuery для отправки запроса, код может выглядеть следующим образом:

    var token = $('meta[name="csrf-token"]').attr('content');
    $.ajax({
        url: '/your-route',
        type: 'POST',
        data: {
            _token: token,
            // Другие данные для отправки
        },
        success: function(response) {
            // Обработка успешного ответа
        },
        error: function(xhr) {
            // Обработка ошибки
        }
    });

    var token = $('meta[name="csrf-token"]').attr('content'); $.ajax({ url: '/your-route', type: 'POST', data: { _token: token, // Другие данные для отправки }, success: function(response) { // Обработка успешного ответа }, error: function(xhr) { // Обработка ошибки } });

    Обратите внимание, что в данном примере мы добавляем токен в объект данных с ключом '_token'. Laravel автоматически проверит наличие этого токена при отправке POST запроса и защитит ваше приложение от CSRF атак.

    Таким образом, вы можете отправить POST запрос с CSRF токеном для Laravel, следуя вышеприведенным инструкциям.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно