İstemciden gelen FileName’i Path.Combine içine koyup dosyayı o adla saklamak kolay görünüyor. Aynı adı iki kullanıcı gönderdiğinde veya ad yol parçaları içerdiğinde ne olacağı ise bu satırdan anlaşılmıyor. Görünen adla depolama anahtarını ayırabiliriz: kullanıcı dosyasını tanıyacağı adı verir, sunucu kendi oluşturduğu anahtarla saklar. Böylece hangi fiziksel dosyanın açılacağına request içindeki metin karar vermemiş olur.
Örnekte kullanıcı bir rapor eki yüklüyor. Dosya önce özel bir depolama alanına alınıyor, metadata kaydı tutuluyor ve gerekiyorsa içerik kontrolü tamamlandıktan sonra indirilebilir hale geliyor. Bu yazının odağı dosya adının ve dosya ömrünün güvenli yönetimi. Bir dosyayı rastgele adla kaydetmenin içeriğini zararsız hale getirdiğini iddia etmiyoruz. Dosya türü doğrulaması ve zararlı içerik kontrolü ayrı ihtiyaçlar olarak kalıyor.
Kod .NET 8 ve ASP.NET Core IFormFile ile kullanılabilir. Örnekte beş MiB uygulama sınırı var; bu her ürün için doğru limit değildir. HTTP request limiti, multipart parser limiti ve depolama sınırı da bu kararla uyumlu kurulmalı. Yalnızca dosya kopyalama metodundaki bir if’e güvenmek, request’in daha önce tükettiği kaynakları sınırlamaz. Boyut kontrolü veri akışının birkaç aşamasında anlam taşır.
Dosya adını kimin seçtiğini ayırmak
İstemcinin FileName alanı, kullanıcının gönderdiği metadata’dır. Sunucunun nerede dosya oluşturacağını belirleyen bir yetki belgesi değildir. Dosyayı kendi ürettiğimiz bir anahtarla saklayıp özgün adı yalnızca gösterim için tutabiliriz. Böylece iki kullanıcı aynı rapor.pdf adını gönderdiğinde aynı fiziksel dosyanın üzerine yazmak zorunda kalmayız. Depolama kimliği ile görünen ad farklı amaçlara hizmet eder.
Path.GetFileName kullanımı, gösterilecek adı sadeleştirmeye yardımcı olabilir. Fakat güvenli depolama tasarımını yalnızca bu çağrıya emanet etmemeliyiz. Yol ayırıcılarının işletim sistemi yorumları farklı olabilir; adın içeriği daha sonra başka bir sisteme taşınabilir. Bizim ana güvence noktamız, özgün adın fiziksel depolama yoluna hiç katılmamasıdır. Bu sınır, basit bir temizleme algoritmasından daha açık bir sözleşme sunar.
var originalName = Path.GetFileName(
file.FileName.Replace('\\', '/'));
var id = Guid.NewGuid();
var storageKey = id.ToString("N") + ".upload";
var targetPath = Path.Combine(privateRoot, storageKey);
privateRoot uygulamanın güvenilir yapılandırmasından gelen, web üzerinden doğrudan sunulmayan bir klasör olmalı. Bu değeri request body’den almayız. StorageKey, kullanıcı adından bağımsız ve sunucunun ürettiği bir dosya adı. Özgün adı saklasak bile arayüzde doğru encoding ile göstermeliyiz. Bir string’i path’ten ayırmak, onun HTML veya log bağlamında otomatik güvenilir olduğunu söylemez.
Dosya oluştururken var olanı ezmemek
FileMode.Create, aynı yol varsa üzerine yazabilir. Sunucunun yeni bir yükleme anahtarı ürettiği akışta CreateNew kullanmak çakışmanın sessiz veri değişikliğine dönüşmesini önleyebilir. Guid kullanımı çakışma olasılığını çok küçültür; yine de dosya API’sinin çakışma davranışını doğru seçmek gerekir. İstisna durumunu yok saymak yerine, var olan dosyaya dokunmadan hata üretmesini beklemek daha açık bir seçimdir.
Hata temizliği de dosyanın kime ait olduğunu bilmek zorunda. CreateNew çakışma nedeniyle dosyayı açamadığında catch içinde hedefi silersek, bu isteğin oluşturmadığı eski dosyayı kaldırabiliriz. Bu yüzden yalnız path’i bilmek yetmiyor; dosyanın gerçekten bu denemede oluşturulduğunu da takip ediyoruz. Başarılı yazma yolu kadar exception yolu da aynı sahiplik kuralını korumalı. Çakışmanın düşük olasılıklı olması cleanup davranışını önemsiz yapmıyor.
Boyutu kopyalama sırasında da sınırlamak
Aşağıdaki örnek dosyayı bütün olarak byte dizisine almadan kopyalar. IFormFile.Length ilk kontrolü sağlar; döngü sırasında okunan toplam byte için de sınır uygulanır. Metot, özel depolama alanı önceden hazırlanmış kabul edilerek yazıldı. Directory.CreateDirectory ile request’ten gelen rastgele klasörler oluşturmuyoruz.
public sealed record StoredUpload(
Guid Id,
string OriginalName,
string StorageKey,
long Length);
public static async Task<StoredUpload> SaveAsync(
IFormFile file,
string privateRoot,
ILogger logger,
CancellationToken ct)
{
const long maxBytes = 5 * 1024 * 1024;
if (file.Length is <= 0 or > maxBytes)
throw new InvalidDataException("Dosya boyutu desteklenmiyor.");
var name = Path.GetFileName(file.FileName.Replace('\\', '/'));
if (string.IsNullOrWhiteSpace(name) || name.Length > 200)
throw new InvalidDataException("Dosya adı desteklenmiyor.");
var id = Guid.NewGuid();
var key = id.ToString("N") + ".upload";
var path = Path.Combine(privateRoot, key);
var created = false;
long total = 0;
try
{
await using (var output = new FileStream(
path,
FileMode.CreateNew,
FileAccess.Write,
FileShare.None,
bufferSize: 64 * 1024,
options: FileOptions.Asynchronous))
{
created = true;
using var input = file.OpenReadStream();
var buffer = new byte[64 * 1024];
int read;
while ((read = await input.ReadAsync(buffer, ct)) > 0)
{
total += read;
if (total > maxBytes)
throw new InvalidDataException("Dosya çok büyük.");
await output.WriteAsync(buffer.AsMemory(0, read), ct);
}
if (total == 0)
throw new InvalidDataException("Dosya boş.");
}
return new StoredUpload(id, name, key, total);
}
catch
{
if (created)
{
try { File.Delete(path); }
catch (Exception cleanupError)
{
logger.LogWarning(
"Upload cleanup failed: {Id}; {ErrorType}",
id,
cleanupError.GetType().Name);
}
}
throw;
}
}
Çıktı stream’inin kapsamını catch’ten önce kapatıyoruz. Özellikle Windows’ta açık dosya handle’ı varken silme denemesi farklı sonuç verebilir. created işareti de dosyayı bu isteğin oluşturduğunu anlatıyor. Cleanup başarısız olursa asıl exception kaybolmuyor; ayrıca iz bırakılıyor. Bu, artık dosyaların hiçbir zaman yetim kalmayacağı garantisi değildir. Depolama temizliği için ayrı bir uzlaştırma yolu gerekebilir.
Metot başarılı döndüğünde dosya yalnızca özel alana alınmıştır. İçeriği onaylanmış, virüs taraması yapılmış veya kullanıcının herkese paylaşma yetkisi doğrulanmış sayılmaz. Bu aşamayı metadata’da PendingScan gibi bir durumla temsil etmek mümkün. Böyle bir alanın adı tek başına tarama yapmaz; indirilebilir hale geçişi gerçekten hangi bileşenin yaptığı belirlenmeli. Bekleyen dosyayı public klasöre koyup yalnızca veritabanında gizlemek yeterli bir erişim sınırı değildir.
IFormFile bütün request akışını sınırsız yapmaz
IFormFile ile model binding sırasında framework bellek veya geçici dosya kullanabilir. Yukarıdaki kopyalama döngüsü request’in daha önceki bu maliyetlerini kontrol etmez. Bu yüzden endpoint ve hosting katmanındaki body limitleri ayrıca seçilmeli. Çok büyük dosyalarda unbuffered multipart okuma gibi farklı bir akış gerekebilir. Bu yazıdaki metodu sınırsız boyutta dosya kabul eden bir upload motoru gibi genellememeliyiz.
Limitin yalnızca reverse proxy’de bulunması da yeterli olmayabilir; uygulama başka bir yoldan erişilebilir olabilir. Yalnızca uygulamada bulunması ise proxy’nin daha önce tükettiği kaynakları kontrol etmeyebilir. Katmanların limitleri aynı ürün kararını desteklemeli. Form overhead’i ile dosyanın kendi byte sayısı da farklıdır. Beş MiB dosya kabul etmek için request boyutunu tam aynı byte değerine sabitlemek, multipart sınırları nedeniyle beklenmeyen redlere yol açabilir.
ASP.NET Core 8’de form dosyası alan Minimal API endpoint’leri için antiforgery gereksinimi de gözden geçirilmeli. Cookie tabanlı akışta korumayı sırf hatayı kaldırmak için devre dışı bırakmak doğru bir varsayım değildir. Uygulamanın kullandığı endpoint modeli, authentication biçimi ve istemci form sözleşmesi birlikte kurulmalı. Dosya kaydetme metodunun doğru olması, HTTP girişinin bütün güvenlik ayarlarını tamamlamaz. Mevcut uygulama sınırlarını korumak gerekir.
Uzantı ve Content-Type ne kadar güvenilir?
Kullanıcının gönderdiği uzantı ve Content-Type, dosyanın gerçek içeriği için tek başına kanıt değildir. .pdf yazan bir dosya başka içerik taşıyabilir. İçerik imzası kontrolü eklenirse bu da seçilen biçimin yalnızca bazı özelliklerini doğrular. Dosyanın bütün yapısının geçerli veya zararsız olduğu sonucu otomatik çıkmaz. Gereksinime göre parser, tarayıcı veya başka bir içerik kontrolü gerekebilir. Her kontrol kendi sınırıyla anlatılmalı.
Dosya türlerini whitelist ile sınırlamak, ürünün desteklemediği biçimleri baştan reddetmeye yardımcı olabilir. Fakat tür kontrolünü yalnızca arayüzde yapmak yetersizdir. Farklı bir istemci aynı endpoint’e doğrudan istek gönderebilir. Sunucu dosya politikasını kendisi uygulamalı. Bu politikada yalnızca teknik uzantılar değil, işin gerçekten hangi dosyaları kabul etmek istediği de belirlenmeli. Her olası formatı desteklemek bakım ve güvenlik alanını büyütür.
Tarama tamamlanana kadar dosyanın başka bir işleyici tarafından açılmaması da düşünülmeli. Örneğin thumbnail üreticisi otomatik olarak her yeni dosyayı parse ediyorsa, PendingScan durumunun önünde başka bir tüketim yolu bulunabilir. Veri yaşam döngüsü yalnızca yükleme endpoint’inden ibaret değildir. Dosyayı okuyan bütün bileşenlerin hangi durumda çalışabileceği açık olmalı. Bir klasör adını quarantine yapmak tek başına erişim engeli oluşturmaz.
Dosya ile metadata aynı transaction’da değil
Dosya kopyalanıp metadata kaydı başarısız olursa diskte sahipsiz dosya kalabilir. Önce metadata yazarsak da kopyalama hatasında dosyası olmayan kayıt oluşabilir. İki adımı aynı metoda koymak veya SQL transaction’ı açmak dosya sistemini otomatik olarak aynı atomik işleme katmaz. Bu ara durumların nasıl bulunup düzeltileceğini ayrıca belirlemek gerekir. Başarısızlıkta neyin kalabileceğini yazmak, her hatayı tek catch içinde gizlemekten daha yararlı bir başlangıç.
Küçük bir uygulamada bekleyen yükleme kaydı, tamamlandı durumu ve periyodik uzlaştırma yeterli olabilir. Daha büyük sistemde storage olayları veya ayrı işlem akışı kullanılabilir. Bunları sırf dosya yüklemesi var diye baştan kurmak şart değil. Önce hangi ara durumların mümkün olduğunu ve nasıl fark edileceğini yazmak gerekir. Başarısız yüklemeyi başarılı göstermemek, bütün hataları tek catch ile saklamamaktan başlar.
Kullanıcıya dönülen kimlik de fiziksel path olmamalı. İndirme isteğinde kimlik üzerinden metadata bulunur, kaynak yetkisi doğrulanır ve depolama anahtarı sunucuda çözülür. Kullanıcının daha önce dosyayı yüklemiş olması her zaman sınırsız paylaşım veya silme yetkisi vermez. Organizasyon sınırı ve dosyanın durumu bu karara dahil olabilir. Depolama anahtarı ile authorization modeli ayrı tutulmalı.
Aynı dosya adını farklı sistemlere taşımak
Dosya daha sonra e-posta eki, ZIP içeriği veya başka storage anahtarı olarak kullanılabilir. Bu alanların her birinin kendi adlandırma ve encoding kuralları vardır. İlk upload sırasında yapılan sadeleştirmeyi bütün gelecek bağlamlar için yeterli saymamak gerekir. Özgün adı yalnızca metadata olarak saklamak bu nedenle yararlı bir ayrım sağlar. Her tüketici, kendi bağlamındaki güvenli gösterimi seçebilir.
Örneğin ZIP üretirken depolama yolunu arşiv içi ad olarak kullanmak gereksiz bilgi paylaşabilir. Kullanıcıya gösterilen adla arşiv içinde yol üretilecekse o bağlamın kuralları uygulanmalı. Benzer biçimde logda ham dosya adını saklamak kişisel veya başka hassas içerik taşıyabilir. Bir alanın dosya sistemi için güvenli olması, log veya HTML için güvenli olduğunu söylemez. Bağlam değiştiğinde kontrol sınırı da yeniden ele alınmalıdır.
Testte hangi dosya adları bulunmalı?
Aynı özgün adla iki yükleme yapıldığında farklı depolama anahtarı üretildiği ve ilk dosyanın içeriğinin değişmediği kontrol edilebilir. Yol ayırıcıları içeren bir ad verildiğinde fiziksel dosyanın hâlâ yalnızca sunucunun ürettiği key ile özel kök altında oluşturulduğu görülmeli. Bu test adın güzel görünmesinden daha önemli bir sınırı denetler: kullanıcı metni, fiziksel hedefi belirlemiyor.
Boyut için boş dosya, sınırın iki tarafı ve kopyalama sırasında sınırı aşan stream ayrı denenebilir. İptal geldiğinde kısmi dosyanın nasıl ele alındığı da kontrol edilmeli. Cleanup’ın başarısız olduğu durumda logun asıl dosya içeriğini veya gizli path ayrıntılarını sızdırmadığı incelenebilir. Bunlar başarılı bir küçük dosya yüklemesinden farklı hata yollarıdır. Testlerin yalnızca son dosyanın varlığını kontrol etmesi yeterli olmayabilir.
İçerik doğrulama veya tarama bu metotta yoksa test raporunda varmış gibi yazılmamalı. Dosya adının ayrılması, overwrite kontrolü ve boyut sınırı farklı güvencelerdir. Bunları geçti diye dosyanın zararsız olduğunu söyleyemeyiz. Üretime uygun bir upload akışı, dosyanın daha sonra kim tarafından ve hangi programla açılacağını da düşünmelidir. Kaydetme adımının küçük kalması, bu sorumlulukların görünmez olması demek değildir.
Bu akışta üç ayrı karar var: görünen adı kullanıcıdan alıyoruz, depolama kimliğini sunucuda üretiyoruz, dosyanın kullanılabilir durumunu uygulamada belirliyoruz. Bunları tek path string’inde birleştirmediğimizde hem indirme yetkisini hem yarım yüklemeyi daha açık yönetebiliriz. Dosya özel alana kopyalandığında içerik kontrolünün ve paylaşım kararının da tamamlandığını varsaymayız. Sonraki tüketicinin hangi durumda dosyayı açabileceği aynı yaşam döngüsünde belli olmalı.
Dosyanın durumunu görünür bir modele bağlamak
Dosya adını arayüzde göstermek gerektiğinde HTML olarak birleştirmemek gerekir. Kullanıcı kontrollü görünen ad, normal metin olarak encode edilmelidir. Sunucuda güvenli anahtar kullanmak arayüzün ayrı çıktı kodlama sorumluluğunu ortadan kaldırmaz. Aynı değer e-posta, log veya HTTP başlığında kullanıldığında o bağlamın kuralları geçerlidir. Tek bir güvenli dosya adı helper’ının bütün çıktı türlerini otomatik koruduğunu düşünmek yanıltıcı olur.
Yükleme formunda cookie tabanlı oturum kullanılıyorsa CSRF koruması ayrıca değerlendirilir. Dosyanın içeriği zararsız olsa bile başka bir sitenin kullanıcının oturumuyla istenmeyen yükleme başlatması mümkün olmamalıdır. API’nin kimlik doğrulama biçimi ve framework’ün form davranışı bu kararı etkiler. Örnekteki dosya kopyalama sınıfı HTTP güvenliğinin tamamını üstlenmez; endpoint sınırındaki kimlik doğrulama, yetki ve istek doğrulamasıyla birlikte kullanılır.
Bir dosyanın checksum’ını almak tekrarları bulmaya yardımcı olabilir. Ancak aynı içeriğin farklı kullanıcılar arasında depolama düzeyinde paylaşılması yeni erişim ve silme soruları doğurur. Bir kullanıcının dosyayı silmesi diğer kullanıcının kaydını etkilememeli. Bu ihtiyaca sahip olmayan küçük bir uygulamada içerik bazlı ortak depolama eklemek gereksiz olabilir. Önce gerçekten tekrar maliyeti ölçülmeli; güvenli adlandırma işini depolama optimizasyonuyla aynı anda büyütmemek daha kontrollü bir başlangıçtır.
Diskte dosyanın bulunması tek başına yüklemenin tamamlandığı anlamına gelmiyor. Kopyalama bitmiş olabilir, fakat metadata henüz kaydedilmemiş veya içerik kontrolü bekliyor olabilir. Birkaç açık durum alanıyla bu farkı küçük uygulamada da gösterebiliriz. Yeni bir workflow motoru kurmak gerekmiyor; yarım kalan dosyanın hazırmış gibi kullanılmasını engellemek istiyoruz. Hata sonrasında hangi adımın kaldığını bildiğimizde temizliği de yalnız bize ait kaynaklara uygulayabiliriz.
Örneğin yükleme kaydı önce hazırlanıyor durumunda oluşturulabilir. Dosya özel depolamaya yazılır, gerekli kontroller tamamlanır ve kayıt hazır durumuna geçer. Bu sırada hata olursa neyin temizleneceği belli olur. Ancak bu akış dosya sistemi ile SQL transaction’ını otomatik birleştirmez. Her geçişin tekrar çalıştırıldığında ne yaptığı düşünülmelidir. Kapanan process’in bıraktığı geçici dosyalar için ayrı ve sınırlı bir temizlik işi gerekebilir.
Temizlik işi dosya adından hareketle bütün bilinmeyen dosyaları silmemeli. Aktif yükleme ile gerçekten sahipsiz kalan dosyayı ayıran güvenilir kayıt gerekir. Yalnızca değiştirilme tarihine göre agresif silme yapmak yavaş süren yüklemeyi bozabilir. Bekleme süresi, aktif işlem bilgisi ve metadata ilişkisi birlikte değerlendirilebilir. Silinen dosyanın hangi kurala göre sahipsiz sayıldığı izlenebilir olmalıdır. Hata düzeltme kodunun yeni veri kaybı üretmemesi önemlidir.
Rastgele ad erişim denetiminin yerine geçmez
GUID tabanlı depolama anahtarı, kullanıcının dosya yolunu seçmesini önler. Bunun yanında dosyanın kim tarafından okunabileceğine ilişkin ayrı bir yetki kuralı gerekir. Başka kullanıcı geçerli anahtarı öğrendiğinde dosyayı indirebiliyorsa yalnızca tahmin edilmesi zor bir adres kullanılmış olur. Özel klasörde tutulan dosyayı yetkili bir endpoint üzerinden sunmak, bu sınırı açık kurmanın yollarından biridir. Anahtarın rastgele olması ile erişimin yetkili olması farklı güvencelerdir.
Aynı ayrım dosya silme ve yeniden adlandırma yollarında da korunmalı. Yükleme endpoint’inde sahiplik kaydı doğru oluşturulsa bile silme endpoint’i yalnızca dosya kimliğine bakıyorsa başka bir açık oluşabilir. Dosyanın bütün yaşam döngüsünü aynı kaynak olarak görmek gerekir. Listeleme, önizleme, indirme, silme ve paylaşma işlevleri ayrı HTTP yolları olsa da aynı erişim kararına bağlı olabilir. Birini test edip diğerlerini güvenli varsaymamak gerekir.
Paylaşılabilir bağlantı gerekiyorsa bunun süresi, kapsamı ve iptal davranışı tanımlanmalı. İç depolama yolunu doğrudan dışarı vermek en kısa çözüm gibi görünür; fakat daha sonra erişimi geri alma ihtiyacını zorlaştırabilir. Her uygulamaya imzalı bağlantı sistemi eklemek zorunlu değildir. Önce gerçekten hesap dışı paylaşım gerekip gerekmediği belirlenir. İhtiyaç yoksa mevcut kimlik doğrulama ve kaynak yetkisiyle ilerlemek daha sade olabilir.
Dosya türünü doğrulamak ne kadar ileri gider?
Uzantı listesi ve Content-Type kontrolü yararlıdır; fakat ikisi de dosyanın zararsız olduğunu kanıtlamaz. İçerik imzası kontrolü de kabul edilen formatın yalnızca bir bölümünü doğrulayabilir. Kullanım amacı görüntü göstermekse dosyayı güvenilir bir kütüphaneyle açıp beklenen temsil üzerinden yeniden üretmek düşünülebilir. Bu kez decoder sınırları, görüntü boyutu ve kaynak tüketimi değerlendirilmelidir. Her doğrulama adımının neyi kontrol ettiği açıkça bilinmelidir.
Arşiv dosyaları daha farklı bir sınır taşır. Sıkıştırılmış dosyanın küçük olması açıldığında küçük kalacağı anlamına gelmez. İçindeki dosya sayısı, toplam açılmış boyut ve path değerleri ayrı kurallar isteyebilir. Bu yazıdaki özel klasöre tek dosya kopyalama örneği güvenli arşiv açma çözümü olarak sunulmuyor. Ürün arşiv içeriğini işleyecekse o adım için ayrıca tehdit ve kaynak sınırı değerlendirmesi gerekir. Bir kontrolü başka işlem için yeterli saymamak gerekir.
Yüklenen belgenin tarayıcıda inline gösterilmesi de indirmeden farklı risk taşır. HTML veya aktif içerik barındırabilen dosyaları aynı origin altında doğrudan açmak uygulamanın güvenlik sınırını etkileyebilir. Dosyanın nasıl sunulacağı, Content-Type ve Content-Disposition gibi başlıklarla birlikte düşünülmelidir. Sadece yükleme anında uzantıyı değiştirmek bu davranışı çözmez. Kabul edilen dosya türü, işleneceği yer ve sunum biçimi aynı tasarımın parçalarıdır.
Boyut limiti tek dosya sınırından daha geniştir
Kodda dosya başına beş MiB sınırı uygulamak, request’in tamamının veya kullanıcının toplam depolamasının sınırlandığını göstermez. Birden fazla dosya, ek form alanları ve eşzamanlı yüklemeler başka maliyetler oluşturabilir. Framework ve reverse proxy’nin request sınırları bu nedenle ayrıca incelenmelidir. Uygulama seviyesindeki kopyalama kontrolü, altyapının çok büyük gövdeyi kabul etmesinden doğan bütün yükü ortadan kaldırmaz.
Kullanıcı başına kota gerekiyorsa eşzamanlı iki yüklemenin aynı boş alanı görmesi mümkündür. Önce kalan kotayı oku sonra dosyayı kabul et yaklaşımı yarışa açıktır. Kullanılan metadata kaynağında uygun rezervasyon veya atomik sınır uygulanabilir. Bunun ayrıntısı depolama ve ürün gereksinimine bağlıdır. Sadece dosya boyutunu toplamak toplam kapasitenin her koşulda korunacağını garanti etmez. Özellikle başarısız yükleme rezervasyonunun ne zaman bırakılacağı açık olmalıdır.
Çok yavaş yükleme de açık bağlantı ve kaynak tutabilir. Boyut sınırının yanında süre, eşzamanlılık ve iptal davranışı değerlendirilir. Ancak bütün kullanıcıları aynı kısa süreye zorlamak gerçek ağ koşullarında kullanılabilirliği bozabilir. Ölçüm ve ürün beklentisiyle uyumlu sınırlar seçmek gerekir. Güvenli dosya yönetimi yalnızca path traversal önleme konusu değildir; kaynağın nasıl tüketildiğini kontrol etmeyi de içerir. Her katmanın sınırını ayrı kaydetmek teşhisi kolaylaştırır.
Çakışma ve hata yollarını ayrı ayrı denemek
CreateNew mevcut dosyanın üzerine yazılmasını engeller. Çakışma testinde önce beklenen hedef adıyla sentetik dosya oluşturup yazma denemesinin onu değiştirmediğini kontrol edebiliriz. Bu durumda temizleme kodunun önceden var olan dosyayı silmemesi gerekir. Örnekte created bayrağı bu nedenle kullanılıyor. Temizlik sadece bu işlem tarafından oluşturulan yarım dosyaya uygulanır. Rastgele anahtarın çakışması düşük olasılıklı olsa da hata yolunun doğru olması bağımsız bir gereksinimdir.
Boyut sınırı testinde hem tam sınır hem bir byte fazlası denenmeli. Kaynak stream ortada hata ürettiğinde yarım dosyanın kaldırıldığı da kontrol edilir. İptal, disk yazma hatası ve metadata kaydı hatası farklı adımlarda oluşur; aynı senaryo gibi ele alınmamalıdır. Testin sonunda depolama klasörü ve metadata birlikte okunur. Sadece dönen exception’a bakmak, arka planda sahipsiz dosya kalıp kalmadığını göstermez. Dosya yaşam döngüsünü doğrulayan kanıt son durumdur.
Yetki tarafı için ASP.NET Core Identity yazısı ilgili bir okumadır. Dosya kabulü ve storage sınırları Microsoft upload rehberinde, kontrol kapsamı OWASP File Upload Cheat Sheet’te, form güvenliği ASP.NET Core antiforgery belgesinde açıklanıyor.
