İçeriğe geç
Çılgın Yazılım

DevOps ve Sistem Yönetimi kod örnekli

Bulut Depolamada İmzalı URL: Dosyayı Sunucudan Geçirmeden Vermek

Her dosya indirmesini uygulama sunucusundan geçirmek hem yavaş hem pahalıdır. İmzalı URL bu yükü tamamen kaldırır.

Çılgın Yazılım 3 dk okuma

Bulut Depolamada İmzalı URL: Dosyayı Sunucudan Geçirmeden Vermek
İçindekiler
  1. Neden sunucudan geçirmek pahalı?
  2. İmzanın mantığı
  3. Yetki kontrolü adresi üretirken yapılır
  4. Doğrudan yükleme: aynı desen ters yönde
  5. Önbellek ve CDN uyumu
  6. Sonuç

Bir imzalı url, belirli bir dosyaya belirli bir süre boyunca erişim veren, kriptografik olarak imzalanmış geçici adrestir. Depolama servisi imzayı doğrular ve süresi dolmuşsa reddeder. Böylece dosyayı uygulama sunucunuzdan geçirmeden, ama yine de yetki kontrolünü koruyarak servis edebilirsiniz.

Sunucudan geçen ve imzalı URL akışlarının karşılaştırması
Uygulama sunucusu dosya taşımak için değil, karar vermek için vardır.

Neden sunucudan geçirmek pahalı?

Klasik akışta dosya iki kez ağdan geçer: depolamadan uygulamaya, uygulamadan istemciye. Bu, bant genişliği maliyetini ikiye katlar. Daha kötüsü, 40 MB'lık bir indirme boyunca bir PHP işçisi tamamen meşgul kalır — eşzamanlı on indirme, on işçiyi bloke eder ve site geri kalan istekler için yavaşlar. Bu tür sessiz kalemleri bulut faturasını şişiren görünmez kalemler yazımızda toplamıştık.

İmzanın mantığı

İmzalı URL sihir değildir: adres + son kullanma zamanı, gizli anahtarla HMAC'lenir. Doğrulayan taraf aynı hesabı yapıp karşılaştırır. Kendi dosya sunucunuzda bile aynı deseni kurabilirsiniz.

PHP
final class ImzaliBaglanti
{
    public function __construct(private string $gizliAnahtar) {}

    public function uret(string $yol, int $gecerlilikSaniye = 300): string
    {
        $bitis = time() + $gecerlilikSaniye;
        $imza  = $this->imzala($yol, $bitis);

        return base_url('dosya/' . ltrim($yol, '/'))
            . '?bitis=' . $bitis . '&imza=' . $imza;
    }

    public function dogrula(string $yol, int $bitis, string $imza): bool
    {
        if ($bitis < time()) {
            return false;                       // süresi dolmuş
        }

        // hash_equals: zamanlama saldırısına karşı sabit süreli karşılaştırma
        return hash_equals($this->imzala($yol, $bitis), $imza);
    }

    private function imzala(string $yol, int $bitis): string
    {
        return hash_hmac('sha256', ltrim($yol, '/') . '|' . $bitis, $this->gizliAnahtar);
    }
}

Karşılaştırmayı === ile yapmayın. hash_equals, imzayı karakter karakter erken çıkışsız karşılaştırır; aksi hâlde saldırgan yanıt sürelerini ölçerek imzayı adım adım tahmin edebilir.

Yetki kontrolü adresi üretirken yapılır

İmzalı URL'nin sık gözden kaçan tarafı budur: adres üretildikten sonra artık kimlik kontrolü yoktur; adrese sahip olan herkes dosyayı indirir. Bu yüzden üretim anında yetkiyi kesin olarak doğrulamak ve süreyi kısa tutmak gerekir.

PHP
public function indirmeBaglantisi(int $dosyaId)
{
    $dosya = $this->dosyaModel->find($dosyaId);
    if (! $dosya) {
        return $this->response->setStatusCode(404)->setJSON(['hata' => 'Dosya yok.']);
    }

    // IDOR koruması: kayıt gerçekten bu kullanıcının kapsamında mı?
    if (! $this->policy->erisebilir(session()->get('user_id'), $dosya)) {
        return $this->response->setStatusCode(403)->setJSON(['hata' => 'Yetkiniz yok.']);
    }

    return $this->response->setJSON([
        'url'   => $this->imzali->uret($dosya['yol'], 120),   // 2 dakika yeter
        'bitis' => time() + 120,
    ]);
}

Doğrudan yükleme: aynı desen ters yönde

Yükleme tarafında da aynı yaklaşım geçerlidir. Sunucu yalnızca imzalı bir yükleme adresi üretir; dosya tarayıcıdan doğrudan depolamaya gider. Ancak burada iki ek önlem şarttır: izin verilen içerik tipini ve maksimum boyutu imzanın parçası yapmak. Aksi hâlde imzalı adresi alan biri, oraya istediği türde ve boyutta veri yükleyebilir.

JavaScript
// 1) Sunucudan imzalı yükleme adresi iste
const { url, alanlar } = await (await fetch('/api/v1/dosya/yukleme-izni', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ad: dosya.name, tip: dosya.type, boyut: dosya.size }),
})).json();

// 2) Dosyayı DOĞRUDAN depolamaya gönder — uygulama sunucusu devrede değil
const form = new FormData();
Object.entries(alanlar).forEach(([k, v]) => form.append(k, v));
form.append('file', dosya);

const yanit = await fetch(url, { method: 'POST', body: form });
if (!yanit.ok) throw new Error('Yükleme başarısız');

Adres üretimi ucunu herkese açık bırakacaksanız, kötüye kullanımı sınırlamak için hız sınırlama uygulayın.

Önbellek ve CDN uyumu

İmzalı adresler her üretimde değiştiği için CDN önbelleğinde tekrar kullanılamaz. Herkese açık ve sık istenen dosyalarda (ürün görselleri, statik varlıklar) imzalama gereksizdir ve zararlıdır — önbellek stratejileri yazımızdaki ayrım burada da geçerlidir: gizli olan imzalanır, açık olan önbelleklenir. Sır yönetimi tarafında ise imzalama anahtarının kaynak koda girmemesi kritiktir; sırların yönetimi yazımız bu konuyu ele alıyor. Sağlayıcı tarafındaki resmî akış için MDN Content-Disposition belgeleri indirme davranışını netleştirir.

Sonuç

İmzalı URL, uygulama sunucusunu veri taşıma işinden kurtarıp yalnızca karar verme işinde bırakır. Kazanç üç yönlüdür: bant genişliği maliyeti yarıya iner, işçi havuzu büyük indirmelerle tıkanmaz ve indirme hızı depolama servisinin ağına devredilir. Karşılığında tek bir disiplin gerekir — yetkiyi adres üretilirken kesin olarak kontrol edin, süreyi ihtiyacın üzerine çıkarmayın, imzayı sabit süreli karşılaştırma ile doğrulayın ve yükleme adreslerinde tip/boyut sınırını imzanın parçası yapın. Bir sonraki büyük dosya indirme özelliğinde, dosyayı sunucudan geçirmeden önce bu deseni değerlendirin.

Beğeniniz benzer içerikleri öne çıkarmamıza yardımcı olur.

Sık sorulan sorular

İmzalı URL süresi ne kadar olmalı?

Kullanım senaryosunun gerektirdiği en kısa süre. Tek tıklamalık indirme için 1-2 dakika fazlasıyla yeterlidir. Uzun süreler adresin paylaşılma ve günlüklerde kalma riskini artırır; "her ihtimale karşı" bir saat vermek yaygın ama gereksiz bir alışkanlıktır.

Adres sızarsa ne olur?

Süresi dolana kadar o dosyaya erişilebilir. Bu yüzden süre kısa tutulur. Ek koruma isteniyorsa imzaya istemci IP adresi veya tek kullanımlık bir jeton eklenebilir, ancak IP tabanlı kısıt mobil ağlarda yanlış pozitif üretebilir.

Küçük dosyalarda da imzalı URL kullanmalı mıyım?

Zorunlu değil. Birkaç kilobaytlık dosyalarda sunucudan geçirmenin maliyeti ihmal edilebilir ve tek istekte iş biter. İmzalı URL asıl kazancını büyük dosyalarda ve yüksek eşzamanlılıkta gösterir.

İmzalama anahtarını değiştirirsem ne olur?

O anda dolaşımda olan tüm imzalı adresler anında geçersiz olur. Bu, bir sızıntı durumunda işinize yarayan bir özelliktir; ancak planlı anahtar değişimlerinde kısa süreli hata dalgası yaşamamak için eski anahtarı bir süre daha doğrulamada kabul eden bir geçiş dönemi tanımlayın.

Yazan

Çılgın Yazılım

Ben Evren Çılgın; yazılım geliştirme, web teknolojileri ve sistem tasarımı alanlarında uzmanlaşmış bir geliştiriciyim. Uzun yıllardır hem frontend hem de backend tarafında üretken, ölçeklenebilir ve kullanıcı dostu çözümler üretiyorum.

Hakkımızda Bize ulaşın

Bu konuda bir projeniz mi var?

İhtiyacınızı birkaç cümleyle anlatın; uygun yaklaşımı birlikte belirleyelim.

Projenizi Anlatın

İlgili yazılar

Yorumlar

Henüz yorum yok. Sorunuzu ya da deneyiminizi ilk siz yazın.

Yorum yazın

Yorumunuz onaylandıktan sonra yayınlanır. Ekibimiz gerekirse konuyla ilgili bir yanıt da paylaşır.

Yayınlanmaz; yalnızca gerektiğinde size ulaşmak için.

En az 10 karakter.

Tüm yazılar