Я не знаю наверняка, связана ли эта проблема с использованием Redis для сеансов, но это кажется правдоподобным. Эта проблема возникает только в больших масштабах с производственным трафиком и возникает примерно в 1–2% запросов на вход в систему.
После обновления до laravel 11 и переключения наших сеансов на хранение в Redis (AWS Elasticache Serverless ), мы часто получаем сообщения об ошибках 419 при попытке пользователей войти в систему. 419 означает, что токен CSRF не соответствует тому, что хранится в сеансе.
Похоже, что в этом коммите метод регенерации был изменен, чтобы начать восстановление токена CSRF в сеансе при входе в систему. Ранее вызывался только ->migrate(), который не должен генерировать новый токен CSRF.
Признак AuthenticatesUsers sendLoginResponse вызывает этот метод восстановления.
Я добавлено ведение журнала в структуру laravel, чтобы попытаться отладить проблему, код, который я изменил, приведен ниже. Судя по журналам, токен CSRF генерируется при загрузке страницы входа в систему, а затем восстанавливается, когда они отправляют запрос POST для входа в систему. Затем он сравнивает токен CSRF, отправленный с токеном, только что созданным с помощью запроса, что приводит к несоответствию.
В примере ниже:
16:42:08: Пользователь попадает на страницу входа, и запускается сеанс, который генерирует токен CSRF для сеанса, который передается странице.
16:42:13: пользователь отправляет сообщения на маршрут входа в систему, вызывается метод regenerate и генерируется новый токен CSRF. Затем можно увидеть, что сравнение CSRF не удалось, поскольку он считает, что действительным токеном CSRF является тот, который был только что сгенерирован в 16:42:13, а не токен CSRF, который был сгенерирован в 16:42:08.
* * - - [31/Dec/2024:16:42:08 +0000] "GET /admin/login HTTP/1.1" 200 30400 "https://*/admin/grid/day/2024-12-29" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15"
[2024-12-31 16:42:08] .INFO: SESSION DEBUG: start: regenerateToken {"session_id":"GKkRGO4gXaHgv97SNAGwU4IBh528n6aQ3lXNMux6","csrf_token":"fzpmkW7zrN3vVIcZHwag2f4VrqZeqXwPV01Wslv8","ip_address":"*","session_cookie":null}
[2024-12-31 16:42:12] .INFO: SESSION DEBUG: regenerate: regenerateToken {"session_id":"V1tl039u7Zko2FNKnYBmnktpkpjWvYWnbinQ7p10","csrf_token":"uMGctIR0qgYT50LJSM5VRjvMeN6nRU5ZwP143uF2","ip_address":"*","session_cookie":"GKkRGO4gXaHgv97SNAGwU4IBh528n6aQ3lXNMux6"}
* * - - [31/Dec/2024:16:42:13 +0000] "POST /admin/login HTTP/1.1" 419 67720 "https://*/admin/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15"
[2024-12-31 16:42:13] .INFO: SESSION DEBUG: Session ID: V1tl039u7Zko2FNKnYBmnktpkpjWvYWnbinQ7p10 Hash does not match: uMGctIR0qgYT50LJSM5VRjvMeN6nRU5ZwP143uF2 vs fzpmkW7zrN3vVIcZHwag2f4VrqZeqXwPV01Wslv8
Чтобы попытаться исправить это, я перезаписал sendLoginResponse, чтобы вызывать ->migrate() вместо ->regenerate(), который должен был восстановить предыдущее поведение laravel, когда новый Токен CSRF не генерируется при входе в систему. Проблема с этим изменением все еще наблюдается. В этом случае, как ни странно, кажется, что _token не установлен в сеансе, хотя он явно был установлен всего несколько секунд назад. См. примечание ниже: «Для запуска приведенного ниже кода не требуется устанавливать токен».
Пользователь, который попытался войти в систему ниже, является сотрудником, и я подтвердил, что он файлы cookie не были отключены, что в любом случае можно увидеть, поскольку файл cookie сеанса во втором запросе совпадает с файлом cookie первого.
16:03:43:< /strong> Пользователь загружает сайт, который генерирует сеанс.
16:03:47: Пользователь пытается войти в систему, и в этом запросе запускается новый сеанс/генерируется токен CSRF. Система считает, что это действительный токен CSRF сеанса, и сравнивает его с токеном CSRF в 16:03:43, что приводит к несоответствию.
* * - - [07/Jan/2025:16:03:43 +0000] "GET / HTTP/1.1" 200 26101 "https://*/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
[2025-01-07 16:03:43] .INFO: SESSION DEBUG: start: regenerateToken {"session_id":"SSJBXTCoydtRHdDhBBH224SQBYqM5PvrGMiCRzx1","csrf_token":"jhZ6BZ2Vo5212jo4EJo6qEkF1wqHjwDHAT2zVh19","ip_address":"*","session_cookie":"SSJBXTCoydtRHdDhBBH224SQBYqM5PvrGMiCRzx1"}
* * - - [07/Jan/2025:16:03:44 +0000] "GET /login HTTP/1.1" 200 23666 "https://*/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
[2025-01-07 16:03:47] .INFO: SESSION DEBUG: start: regenerateToken {"session_id":"SSJBXTCoydtRHdDhBBH224SQBYqM5PvrGMiCRzx1","csrf_token":"zvn0N1iXxY0eIvC1u6QGbQC1h3XSmxac027GVQBp","ip_address":"*","session_cookie":"SSJBXTCoydtRHdDhBBH224SQBYqM5PvrGMiCRzx1"}
[2025-01-07 16:03:47] .INFO: SESSION DEBUG: Session ID: SSJBXTCoydtRHdDhBBH224SQBYqM5PvrGMiCRzx1 Hash does not match: zvn0N1iXxY0eIvC1u6QGbQC1h3XSmxac027GVQBp vs jhZ6BZ2Vo5212jo4EJo6qEkF1wqHjwDHAT2zVh19
* * - - [07/Jan/2025:16:03:47 +0000] "POST /login HTTP/1.1" 419 67713 "https://*/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
Изменения кода для ведения журнала:
app/Http/Middleware/VerifyCsrfToken.php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
protected function tokensMatch($request)
{
$token = $this->getTokenFromRequest($request);
$is_session_token_string = is_string($request->session()->token());
$is_token_string = is_string($token);
$hash_equals = hash_equals($request->session()->token(), $token);
if (!$is_session_token_string) {
\Log::info('SESSION DEBUG: Session token stored in session is not a string: ' . $request->session()->token());
}
if (!$is_token_string) {
\Log::info('SESSION DEBUG: Token from request is not a string: ' . $token);
}
if (!$hash_equals) {
\Log::info('SESSION DEBUG: Session ID: ' . $request->session()->getId() . ' Hash does not match: ' . $request->session()->token() . ' vs ' . $token);
}
return $is_session_token_string && $is_token_string && $hash_equals;
}
}
Сессия/Store.php:
/**
* Generate a new session identifier.
*
* @param bool $destroy
* @return bool
*/
public function regenerate($destroy = false)
{
return tap($this->migrate($destroy), function () {
$this->regenerateToken();
$ipAddress = Request::header('CF-Connecting-IP', Request::ip());
$sessionId = $this->getId();
$sessionCookieName = config('session.cookie'); // Get session cookie name from config
$sessionCookieValue = Request::cookie($sessionCookieName);
Log::info("SESSION DEBUG: regenerate: regenerateToken", [
'session_id' => $sessionId,
'csrf_token' => $this->token(),
'ip_address' => $ipAddress,
'session_cookie' => $sessionCookieValue,
]);
});
}
/**
* Start the session, reading the data from a handler.
*
* @return bool
*/
public function start()
{
$this->loadSession();
if (! $this->has('_token')) { // regenerateToken();
$ipAddress = Request::header('CF-Connecting-IP', Request::ip());
$sessionId = $this->getId();
$sessionCookieName = config('session.cookie'); // Get session cookie name from config
$sessionCookieValue = Request::cookie($sessionCookieName);
Log::info("SESSION DEBUG: start: regenerateToken", [
'session_id' => $sessionId,
'csrf_token' => $this->token(),
'ip_address' => $ipAddress,
'session_cookie' => $sessionCookieValue,
]);
}
return $this->started = true;
}
Подробнее здесь: https://stackoverflow.com/questions/793 ... with-redis
Laravel 11 периодические ошибки 419 CSRF при входе в систему, сеансы, используемые с Redis ⇐ Php
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Опубликовать запрос в Laravel - Ошибка - 419 Извините, срок вашего сеанса / 419 истек
Anonymous » » в форуме Php - 0 Ответы
- 20 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Опубликовать запрос в Laravel - Ошибка - 419 Извините, срок вашего сеанса / 419 истек
Anonymous » » в форуме Php - 0 Ответы
- 26 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Опубликовать запрос в Laravel - Ошибка - 419 Извините, срок вашего сеанса / 419 истек
Anonymous » » в форуме Php - 0 Ответы
- 15 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Разместите запрос в Laravel - ошибка - 419 Извините, ваша сеанс/ 419 ваша страница истек
Anonymous » » в форуме Php - 0 Ответы
- 28 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Разместите запрос в Laravel - ошибка - 419 Извините, ваша сеанс/ 419 ваша страница истек
Anonymous » » в форуме Php - 0 Ответы
- 7 Просмотры
-
Последнее сообщение Anonymous
-