Докеризованный сервер Laravel отклоняет POST-запросы

Вот полностью воспроизводимый образ докера сервера REST API Laravel:

FROM php
RUN apt-get update
RUN apt-get install zip -y
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
RUN composer create-project laravel/laravel frontend
WORKDIR frontend
COPY web.php web.php
RUN mv web.php routes
EXPOSE 8000
CMD [ "php", "artisan", "serve", "--host", "0.0.0.0" ]

Единственное, что я отредактировал, это одну конечную точку (web.php):

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return csrf_token();
});

Route::post('/', function (Request $request) {
    if ($request->hasFile('source'    )) { return ">> GOOD ! <<"; }
    if ($request->hasFile('input.json')) { return ">> GOOD ! <<"; }

    $x = count($_FILES);

    return "DD >> $x << DD";
});

Я создаю и запускаю образ докера следующим образом:

$ docker build --tag host.translator.php --file Dockerfile .
$ docker run -p 8008:8000 -d -t --name translator.php host.translator.php

Тогда, как говорится в соответствующих постах (здесь , и здесь , , а также здесь):

$ Set-Variable -Name X -Value (curl.exe -X GET -F "[email protected]" http://127.0.0.1:8008/)
# X holds the token:
# echo $X
# U263lUv3dz9PH7ySm3GmgUUjHjjWm78cqofODUmh

Но когда я пытаюсь использовать этот токен, он не работает:

$ curl.exe --header "X-CSRFToken:$X" -X POST -F "[email protected]" http://127.0.0.1:8008/ | Select-String "<title>Page Expired"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6851    0  6609  100   242  80486   2947 --:--:-- --:--:-- --:--:-- 83548

        <title>Page Expired</title>

Любая помощь очень ценится - спасибо!

Обновлено:

#
# used a new variable Z - just to be sure ...
#
$ Set-Variable -Name Z -Value (curl.exe -b cookiejar -X GET -F "[email protected]" http://127.0.0.1:8008/)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   282    0    40  100   242    527   3194 --:--:-- --:--:-- --:--:--  3760
$ echo $Z # this looks good, right ?
aHvU5WOaGs9qxOIzgdYb90TJUKPDgDaNhYjQNALW
#
$ type .\cookiejar # this looks ... hmmm ... good (I think ?)
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_127.0.0.1     FALSE   /       FALSE   1711103819      laravel_session eyJpdiI6IllsOW9KdlVzT1ZPcUJDOUdQRnUyZHc9PSIsInZhbHVlIjoiekpING13WFRaaDRLUHBUcVpNM0VjblBwVjlXM1VrSU1uYUF3dk43d0J6c0RvSDJ5UWZOU3lla1lKVjBNRnNVTXJOaTNMdmt3dlIvdW5HZDk1ODZUb0gxVWMySHh5cXBWeG5XbjVMQlpMQ2xoMzM0ODROQ1FGQ0NMQzFNaHNQMXMiLCJtYWMiOiI0MTg3ZTM0NTlmNWMzZGUyZDY3YzI2YWViYzc2MDZhMjAyMjA2NzE5YmRmYTRmYWRmYzQxODIzYmVlOThlZTkxIiwidGFnIjoiIn0%3D
#
# Now let's cross our fingers extra strong !
#
$ curl.exe -c cookiejar --header "X-CSRFToken:$Z" -X POST -F "[email protected]" http://127.0.0.1:8008/ | Select-String "<title>Pa
ge Expired"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6851    0  6609  100   242  85705   3138 --:--:-- --:--:-- --:--:-- 87833
242  83137   3044 --:--:-        <title>Page Expired</title>- --
:--:-- --:--:-- 85637

Думаю, чтобы его можно было полностью воспроизвести, нам также понадобится содержимое вашего input.json файла :)

Hans Kilian 22.03.2024 09:16

если вы используете токены csrf, вам также необходимо использовать jar cookie, а также сохранять и повторно отправлять файлы cookie, поскольку токен csrf связан с сеансом пользователя, который передается с помощью файлов cookie.

apokryfos 22.03.2024 09:17

@apokryfos, я думал, что единственной важной информацией в файле cookie является токен, не так ли?

OrenIshShalom 22.03.2024 09:19

@HansKilian вот оно :) {"name": "oren", "age": 6}

OrenIshShalom 22.03.2024 09:20

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

apokryfos 22.03.2024 09:21

@apokryfos, ты имеешь в виду, что мне следует каким-то образом добавить дополнительную информацию в запрос POST? или я делаю это совершенно неправильно?

OrenIshShalom 22.03.2024 09:30

Попробуйте отправить запрос на получение, например curl.exe -b cookiejar -X GET -F "[email protected]" http://127.0.0.1:8008/ , и запрос на публикацию, например curl.exe -c cookiejar --header "X-CSRFToken:$X" -X POST -F "[email protected]" http://127.0.0.1:8008/, чтобы сохранить, а затем отправить файлы cookie.

apokryfos 22.03.2024 09:33

@apokryfos, я отредактировал вопрос, чтобы показать ваше предложение - оно все равно не работает

OrenIshShalom 22.03.2024 09:42

@apokryfos Разве не следует поменять местами параметры -b и -c? Согласно справочной странице, -c хранит файлы cookie и -b отправляет их.

Hans Kilian 22.03.2024 09:56

Пробовали ли вы выполнить запрос на публикацию в почтальоне, а затем проверить там код завитка?

Mr. Kenneth 22.03.2024 10:06

@HansKilian, я попробовал это с переключенными флагами -b, -c, но это все равно не работает. Я не использую почтальон, но установлю его, если это поможет (?)

OrenIshShalom 22.03.2024 10:22

@Mr.Kenneth Я установил почтальона и отправил запрос GET (успешно) и запрос POST, который вернул Page Expired, как и раньше... какую настройку мне следует сделать в почтальоне?

OrenIshShalom 22.03.2024 10:29

хм... AFAIK, срок действия страницы - это ошибка 419, отсутствует токен csrf. Попробуйте следовать этому, как добавить токен в почтальоне. stackoverflow.com/a/49249850/13933721

Mr. Kenneth 22.03.2024 10:41

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

Mr. Kenneth 22.03.2024 10:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
14
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

CSRF (подделка межсайтовых запросов) — это способ защитить сервер от подделки.

См. https://laravel.com/docs/11.x/csrf

Чтобы пройти эту проверку обычным способом, вам нужно передать заголовок X-CSRF-TOKEN (а не X-CSRFToken, как вы это сделали с опечаткой) и передать правильный токен CSRF.

Механизм токена CSRF следующий:

  • сайт позволяет запускать некоторые точки входа (например, некоторые GET-запросы) без передачи CSRF
  • и после этого вам необходимо правильно установить заголовок для токенов CSRF для любых запросов POST, которые вы можете отправить.
  • всякий раз, когда обрабатывается страница/запрос, старый токен CSRF аннулируется, и ваш сеанс получит новый токен CSRF, который необходимо передать в следующем POST вместо предыдущего.

Итак, если вы отправляете запрос POST через CURL, то токен CSRF должен быть определен, правда, но вам нужно будет отправить самый новый.

Вы можете исключить URL-адреса из защиты CSRF, но будьте осторожны: по возможности не снижайте стандарты безопасности с помощью

->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ]);
})

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

Оно работает !! Спасибо за подробный ответ! Я думаю, последнее, что я не до конца понял, это то, как содержимое файла cookiejar связано с последним токеном csrf - они оба меняют сам запрос, но это не один и тот же хэш (верно?), хэш cookiejar, кажется, много дольше

OrenIshShalom 24.03.2024 16:27

@OrenIshShalom рад помочь. Я предполагаю, что это разные хеши, но я это не проверял.

Lajos Arpad 24.03.2024 16:53

Другие вопросы по теме