Я использую Laravel 10, Livewire 3 и Jetstream 5. Мой веб-сайт находится в личном домене на собственном сервере. Этот веб-сайт также помещен в iframe, и он должен работать с iframe на другом моем веб-сайте.
Когда пользователи пытаются войти в iframe, они получают 419 Срок действия токена CSRF истек. До изменения настроек ошибка 419 выдавалась, как только пользователь посещал веб-сайт, на котором находится iframe. Имейте в виду, что это происходит только на мобильных устройствах, чаще всего у пользователей iOS, но иногда и у пользователей Android. Итак, пользователь посещает сайт с помощью iframe, и появляется всплывающее окно со страницей ошибки 419, а затем предупреждение с вопросом, хочу ли я обновить страницу. И он застрял в цикле, и страница веб-сайта была практически непригодна для использования на мобильных устройствах.
Однако с текущими настройками и кодом ошибка 419 перестала появляться при посещении страницы, но теперь появляется всякий раз, когда пользователь пытается войти в систему (для /login).
Я провел исследование (Webkit.Org Полная блокировка сторонних файлов cookie | Статья Mozilla Dev о сторонних файлах cookie)
Атрибут src для : https://domain.de/
Текущее состояние моего кода и конфигурации:
Код: Выделить всё
config/session.php
Код: Выделить всё
return [ /*Values in comments are .env values, if nothing, then its not set in the .env*/
'driver' => env('SESSION_DRIVER', 'database'), /*database*/
'lifetime' => env('SESSION_LIFETIME', 120),/*120*/
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => env('SESSION_CONNECTION'),
'table' => 'sessions',
'store' => env('SESSION_STORE'),
'lottery' => [2, 100],
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN'),/*.domain.de*/
'secure' => env('SESSION_SECURE_COOKIE'), /*true*/
'http_only' => true,
'same_site' => 'none',
'partitioned' => true,
];
Код: Выделить всё
config/cors.php
Код: Выделить всё
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['https://www.domain-with-iframe.de'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
Код: Выделить всё
routes/web.php
Код: Выделить всё
//Routes that DON'T require auth/login
Route::middleware([
'web'
])->group(function () {
Route::get('/', function () {/*HOMEPAGE*/
return view('welcome');
});
Route::get('/impressum', [ImpressumController::class, 'show'])->name('impressum.show');
Route::get('listings/view/{listing}', Listing\View::class)->name('listings.view');
Route::get('applications/create/{listing}', Application\Create::class)->name('applications.create');
});
Код: Выделить всё
app/Providers/AppServiceProvider
Код: Выделить всё
public function boot(): void
{
if($this->app->environment('production'))
{
\URL::forceScheme('https');
}
}
Код: Выделить всё
app/Http/Middleware/VerifyCsrfToken
Код: Выделить всё
protected $except = [
'stripe/*',
'paypal/*',
'https://www.domain-with-iframe.de/*',
];
Код: Выделить всё
welcome.blade.php
Код: Выделить всё
{{-- @livewire('listing.pop-up-listing-modal')--}}
@livewire('listing.index-all')
...
Код: Выделить всё
[{{ trim(config('app.name')) }}] {{ trim($__env->yieldContent('title')) }}
@yield('meta-tags')
[*]
@yield('extra-js')
@vite(['resources/css/app.css', 'resources/js/app.js'])
@yield('extra-css')
@yield('code-css')
@livewireStyles
@livewire('navigation-menu')
@if (isset($header))
{{ $header }}
@endif
{{ $slot }}
@include('layouts.footer')
@yield('code-js')
@stack('modals')
@livewireScripts
Я также заметил, что в файле login.blade.php используется гостевой макет, который я забыл разместить здесь:
Код: Выделить всё
@if (session('status'))
{{ session('status') }}
@endif
@csrf
Код: Выделить всё
...
- Убедился:
- Тег @csrf существует после каждой таблицы
- sessions, которая существует и заполнена. Убедитесь, что драйвер сеансов работает (работает для настольных компьютеров)
- Убедился, что таблица сеанса имеет идентификатор в виде varchar
- & 'encrypt' => true
Код: Выделить всё
'encrypt' => false
- Изменено имя файла cookie laravel, чтобы оно содержало только буквы, без дефисов и подчеркиваний.
Код: Выделить всё
SESSION_DOMAIN=
Код: Выделить всё
.domain.de
Код: Выделить всё
domain.de
- Очистка кэша и оптимизация ничего не меняют
Разрешения для папок такие, какие должны быть быть и не были изменены. Я не использую файловый драйвер, несмотря на то, что мой /storage и /vendor имеют разрешения 755 - Убедился, что на действующем сайте есть хороший сертификат SSL
- Laravel 5.7 выдает 419 Ошибка (опубликовано в 2018 г., ответ обновлен в 2021 г.):
- Она связана с Laravel 5, 6 и 7, и поскольку моя работает нормально для настольных компьютеров, но имеет проблемы с мобильной версией, ее несвязано
- Laravel возвращает «419 PAGE EXPIRED;» После входа/регистрации в браузере Chrome, Edge и т. д. [дубликат] (опубликовано в 2022 г.)
- уже нет
Код: Выделить всё
same-site
- потому что у меня есть действующий сертификат SSL
Код: Выделить всё
SESSION_SECURE_COOKIE=true
- Разрыв сеанса Laravel 7 на IFRAME в другом домене (Опубликовано 2020)
- уже нет
Код: Выделить всё
same-site
- Загрузка iFrame через Chrome и Safari — статус 419 (Опубликовано) 2023), что затем приводит к отключению csrf в laravel для определенного маршрута.
- Мне нужна проверка csrf, потому что не иметь ее — плохая практика, к тому же будет много пользователей, я не хочу рисковать нападением. Мой VerifyCsrfToken не должен быть изменен, чтобы включить в него какие-либо другие маршруты моего действующего сайта; Я хочу, чтобы каждый токен CSRF был проверен и проверен, поэтому эта статья не только бесполезна, но и фактически является плохой практикой для обычных маршрутов.
- Когда я пытался закомментировать VerifyCsrfToken. Он больше не выдает 419, но и не регистрирует пользователей. Опять же, ТОЛЬКО на мобильном телефоне. Когда я комментирую это на рабочем столе, все работает нормально, пользователь входит в систему.
- Встраивание формы Laravel в iFrame показывает ошибку 419 (несоответствие токена CSRF).
- То же, что и 4.
- Проблема с Livewire в iFrame
- Мой VerifyCsrfToken уже содержит URL-адрес с iframe в массиве $Exception
- У меня нет маршрута /livewire, поэтому нет необходимости помещать его в массив
- Использовал прокси-сервер отладки IOS Webkit для возьмите вывод консоли через Chrome DevTools.
Мне удалось заставить его работать на настольном компьютере, но он по-прежнему не работает на мобильных устройствах, ни один файл console.log не печатается (хотя на настольном компьютере он работает нормально):
Код: Выделить всё
class CSRFTokenManager {
constructor() {
console.log('CSRFTokenManager constructor called');
this.init();
}
init() {
console.log('Initializing...');
document.addEventListener('DOMContentLoaded', () => {
if (this.inIframe() && this.isMobile()) this.fetchCSRFToken();
else console.log('Not in iframe or not on mobile');
});
}
inIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
isMobile() {
return /Android|webOS|iPhone|iPad|iPod|Opera Mini|Mobile/i.test(navigator.userAgent);
}
fetchCSRFToken() {
console.log('Fetching CSRF token...');
axios.get('/sanctum/csrf-cookie').then(response => {
this.setCSRFToken();
console.log('CSRF token fetched');
}).catch(error => {
console.error('Error fetching CSRF token:', error);
});
}
setCSRFToken() {
const token = this.getCookie('XSRF-TOKEN');
if (token) {
axios.defaults.headers.common['X-XSRF-TOKEN'] = token;
console.log('CSRF token set in axios headers');
} else {
console.error('CSRF token not found in cookies');
}
}
getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
}
new CSRFTokenManager();
Что еще можно попробовать? Как я могу это отладить? Я контролирую оба сайта, тот, у которого есть iframe, — это сайт Ionos.
Подробнее здесь: https://stackoverflow.com/questions/785 ... uest-is-ma