File yüklemeleri ilk bakışta basit görünse de, web uygulamalarında güvenlik açıklarının ve performans problemlerinin en yaygın kaynaklarından biridir. Profil resimleri, faturalar veya belgeler kabul etseniz de, yanlış dosya yönetimi uygulamanızı kötü niyetli dosya çalıştırma, yol geçişi saldırıları veya sunucu kaynaklarının tükenmesi gibi risklere maruz bırakabilir.
Bu rehberde, Laravel’de dosya yükleme için üretime hazır en iyi uygulamaları inceleyeceğiz; bunlar arasında doğrulama, güvenli depolama yöntemleri, benzersiz dosya adı oluşturma ve bulut entegrasyonu yer alıyor.
1. Dosya Türünü ve MIME Türünü Her Zaman Doğrulayın
1. Dosya Türünü ve MIME Türünü Her Zaman Doğrulayın
Kullanıcının sağladığı uzantılara ya da basit MIME başlık kontrollerine asla güvenmeyin. Saldırganlar, bir .php dosyasını kolayca .jpg olarak yeniden adlandırabilir veya istekteki Content-Type başlığını sahteleyebilirler.
Laravel’in içinde yer alan doğrulama kurallarını, özel Form Requests kullanarak uzantıları, içerik tabanlı MIME türlerini ve dosya boyutunu kesin olarak uygulamak için kullanın:
php artisan make:request StoreDocumentRequest
StoreDocumentRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreDocumentRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'document' => [
'required',
'file',
'mimes:pdf,png,jpg,jpeg', // İzin verilen uzantıları zorlar
'mimetypes:application/pdf,image/png,image/jpeg', // Dosya imzasını/magic bytes'i kontrol eder
'max:5120', // Boyutu 5MB ile sınırlar
],
];
}
}
Öneri: mimes ve mimetypes kurallarını birleştirin. Mimetypes kuralı, PHP’nin Fileinfo uzantısını kullanarak dosyanın ikili içeriğini analiz eder ve istemcinin dosya uzantısına dayanmaz.
2. Dosyaları Her Zaman Yayın Klasöründe Doğrudan Saklamayın
2. Dosyaları Her Zaman Yayın Klasöründe Doğrudan Saklamayın
Başlangıçta yapılan büyük bir hata, yüklemeleri public/uploads dizinine kaydetmek veya yüklenen dosyaları web sunucusu tarafından yürütülebilir hale getirmektir. Eğer bir kullanıcı kötü niyetli bir PHP betiği yükler ve onun doğrudan URL’sine ulaşırsa, sunucu bunu çalıştırabilir.
storage/
└── app/
├── private/
3. Rastgele, Tahmin Edilemeyecek Dosya İsimleri Oluşturun
3. Rastgele, Tahmin Edilemeyecek Dosya İsimleri Oluşturun
Kullanıcıdan alınan orijinal dosya adını kullanmak, uygulamanızı aşağıdaki risklere açar:
- Yol Geçişi Saldırıları (../../etc/passwd ya da mevcut dosyaların üzerine yazma).
- Dosya Adı Çakışmaları (İki kullanıcının aynı anda invoice.pdf yüklemesi durumunda).
- Gizlilik Sızıntıları (Dahili kullanıcı dosya adlandırma şemalarının ifşası).
Laravel’in store() metodu, dosya adına otomatik olarak benzersiz, kriptografik olarak güvenli bir hash üretir:
namespace App\Http\Controllers;
use App\Http\Requests\StoreDocumentRequest;
use Illuminate\Http\RedirectResponse;
class DocumentController extends Controller
{
public function store(StoreDocumentRequest $request): RedirectResponse
{
// "a8f3b2c...jpg" gibi bir hash adı otomatik olarak oluşturur
$path = $request->file('document')->store('documents', 'private');
// Orijinal metadata'yı gerektiğinde güvenli bir şekilde veritabanında saklayın
auth()->user()->documents()->create([
'path' => $path,
'original_name' => $request->file('document')->getClientOriginalName(),
'mime_type' => $request->file('document')->getClientMimeType(),
'file_size' => $request->file('document')->getSize(),
]);
return back()->with('success', 'Document uploaded securely.');
}
}
4. Geçici İmzalı URL’ler ile Güvenli Dosya Servisi
4. Geçici İmzalı URL’ler ile Güvenli Dosya Servisi
Özel bir disk veya özel bir S3 bucket’ında saklandığında, dosyalar yetkisiz halka açık indirilmelere karşı korunur. Yetkili kullanıcıların bir dosyayı görüntülemesi veya indirmesi için geçici bir imzalı URL üretin:
Kontrolcünüzde veya API Kaynaklarınızda:
use Illuminate\Support\Facades\Storage;
public function show(Document $document)
{
// Yetkili kullanıcının belgeye sahip olduğunu veya buna erişimi olduğunu doğrulayın
$this->authorize('view', $document);
// 15 dakika geçerli bir geçici indirme URL'si oluşturur
$url = Storage::disk('s3')->temporaryUrl($document->path, now()->addMinutes(15));
return response()->json(['download_url' => $url]);
}
5. Metadata’yı Sil ve Görüntüleri Temizle
5. Metadata’yı Sil ve Görüntüleri Temizle
Akıllı telefonlardan doğrudan yüklenen görüntüler EXIF metadata barındırır (GPS koordinatları, kamera modeli, zaman damgası). Eğer genel kullanıcılar bu görüntülere erişim sağlayabiliyorsa, bu önemli bir gizlilik riski oluşturur.
Intervention/image gibi paketleri kullanarak, yüklenen görüntüleri yeniden kodlayarak ve hassas metadata’yı silerek saklayın:
use Intervention\Image\Laravel\Facades\Image;
use Illuminate\Support\Facades\Storage;
public function uploadAvatar($request)
{
$file = $request->file('avatar');
// EXIF'i okur ve siler
$image = Image::read($file)->encodeByExtension('webp', quality: 80);
$fileName = 'avatars/' . Str::uuid() . '.webp';
Storage::disk('public')->put($fileName, (string) $image);
return $fileName;
}
Üretim için Kontrol Listesi
- [ ] Boyut ve Türü Doğrulayın: mimes ve mimetypes ile belirgin byte-boyut limitleri kullanın.
- [ ] Dosya İsimlerini Rastgeleleştirin: Laravel’in hash adları oluşturmasına izin verin veya Str::uuid() kullanın.
- [ ] Özel Olarak Saklayın: Hassas dosyalar için özel diskler kullanın; izlenmeyen public/ dizinlerinden kaçının.
- [ ] Metadata’yı Silin: Kullanıcı görüntülerini yeniden kodlayarak EXIF/konum verilerini silin.
- [ ] Yüklemeleri Sınırlayın: DoS saldırılarını önlemek için throttle:upload middleware uygulayın.
Ölçeklenebilir Web & Bulut Mimarisi mi Gerekiyor?
Üretime hazır arka uç platformları inşa etmek, güvenlik, dosya yönetimi ve ölçeklenebilir mimari konularında dikkatli bir dikkat gerektirir.
Laravel projelerinizde güvenli dosya yüklemeleri ve özel depolama yöntemlerinizi nasıl yönetiyorsunuz? Yorumlarınızda stratejilerinizi paylaşın!
Kaynak: Orijinal Makale


