Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працює завантаження файлів у Livewire і де в ньому ризики безпеки?

Компонент з трейтом WithFileUploads приймає файли через звичайний wire:model:

use Livewire\WithFileUploads;

new class extends Component {
    use WithFileUploads;

    #[Validate('image|max:2048')]   // 2 МБ
    public $photo;

    public function save(): void
    {
        $this->validate();
        $path = $this->photo->store(path: 'avatars', options: 'public');
        auth()->user()->update(['avatar_path' => $path]);
    }
};
<input type="file" wire:model="photo">
@if ($photo) <img src="{{ $photo->temporaryUrl() }}"> @endif

Як це працює під капотом:

  1. при виборі файлу JavaScript запитує в компонента підписаний URL для завантаження;
  2. файл завантажується за ним у тимчасовий каталог (livewire-tmp/ на диску за замовчуванням);
  3. властивість $photo отримує об'єкт тимчасового файлу (TemporaryUploadedFile);
  4. у вашому методі файл перевіряється й переноситься на постійне місце.

Ризики й захист:

  • глобальна валідація тимчасових завантажень - за замовчуванням file|max:12288 (12 МБ). Тобто ще до вашої валідації сервер приймає будь-який файл до 12 МБ. Звузьте в config/livewire.php (temporary_file_upload.rules), якщо застосунку не потрібні великі файли;
  • обмеження частоти - ендпойнт завантаження за замовчуванням має throttle-middleware; його можна змінити (temporary_file_upload.middleware). Але в Livewire 4 файли понад 1 МБ на локальному диску йдуть частинами (chunked upload) - один файл стає десятками швидких запитів. Надто жорсткий ліміт на кшталт throttle:60,1 ламає великі завантаження;
  • розмір файлу обмежує ваше правило max:, а не upload_max_filesize PHP: частини збираються на сервері, і перерване завантаження продовжується з місця зупинки;
  • перевірка типу - лише через правила валідації (image, mimes:pdf), які перевіряють вміст, а не розширення. Ніколи не зберігайте з оригінальною назвою від користувача без перевірки - використовуйте згенеровану (store() робить саме так);
  • попередній перегляд (temporaryUrl()) працює лише для зображень і через підписаний URL - чужі файли так не подивитися;
  • очищення - на локальному диску Livewire сам видаляє старі тимчасові файли; для S3 треба налаштувати правило життєвого циклу (php artisan livewire:configure-s3-upload-cleanup, файли старші 24 годин);
  • публічність - зберігайте в приватний диск усе, що не призначене для всіх, і віддавайте через підписані URL.

Пряме завантаження в S3 (LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK=s3) знімає навантаження з сервера застосунку: файл іде з браузера одразу в бакет. Але частина правил валідації потребує доступу до файлу - бакет має це дозволяти.

Пастка з назвою: upload - зарезервоване слово Livewire. Метод чи властивість з такою назвою зламають завантаження.

Тести: UploadedFile::fake()->image('avatar.jpg') з ->set('photo', $file) і Storage::fake().

Докладніше в документації: Завантаження файлів

Схожі питання