Przejdź do głównej treści
Grafika przedstawia ukryty obrazek

Statyczne serwowanie plików w PHP i zabezpieczanie przed bezpośrednim dostępem

Statyczne serwowanie plików w PHP i zabezpieczanie przed bezpośrednim dostępem

Wprowadzenie

W wielu aplikacjach webowych zachodzi potrzeba przechowywania i udostępniania plików użytkownikom — mogą to być zdjęcia profilowe, dokumenty, raporty czy prywatne multimedia. Często chcemy jednak, aby dostęp do tych plików był ograniczony, np. tylko dla zalogowanego użytkownika lub tylko poprzez określone warunki. W tym kontekście PHP może być pomocne nie tylko jako język do obsługi logiki serwera, ale także jako pośrednik w bezpiecznym serwowaniu plików.

Czym jest statyczne serwowanie plików?

Statyczne serwowanie plików polega na udostępnianiu zasobów (takich jak obrazy, pliki PDF, pliki wideo) bezpośrednio przez serwer HTTP, np. Apache lub Nginx, bez udziału kodu aplikacji. Taka metoda jest wydajna, ale ma jedną istotną wadę — brak kontroli dostępu.

Przykład:

Plik znajduje się w katalogu /uploads/public/image.jpg, a jego adres to:

https://example.com/uploads/public/image.jpg

Każdy, kto zna ten adres, może uzyskać do niego dostęp — niezależnie od uprawnień.

Problem: Jak chronić pliki przed nieautoryzowanym dostępem?

Jeśli plik powinien być dostępny tylko po spełnieniu określonych warunków (np. tylko po zalogowaniu), bezpośredni dostęp przez przeglądarkę jest niepożądany. W takich przypadkach warto zastosować pośrednie serwowanie plików przez PHP.

Metoda: Serwowanie plików przez PHP

Zamiast udostępniać pliki bezpośrednio, możemy przechowywać je poza publicznym katalogiem WWW, a dostęp do nich realizować przez specjalny skrypt PHP.

Struktura katalogów:

/app
  /uploads (poza katalogiem publicznym)
/public_html
  index.php
  serve.php

serve.php – przykład kodu:

<?php
session_start();

// Sprawdź uprawnienia użytkownika
if (!isset($_SESSION['user_id'])) {
    http_response_code(403);
    exit('Brak dostępu.');
}

// Pobierz nazwę pliku z parametru GET
$filename = basename($_GET['file'] ?? '');

// Ścieżka do chronionego pliku
$filepath = __DIR__ . '/../uploads/' . $filename;

// Sprawdź, czy plik istnieje
if (!file_exists($filepath)) {
    http_response_code(404);
    exit('Plik nie istnieje.');
}

// Wysyłanie nagłówków
header('Content-Type: ' . mime_content_type($filepath));
header('Content-Length: ' . filesize($filepath));
header('Content-Disposition: inline; filename="' . $filename . '"');
readfile($filepath);
exit;

Przykładowe wywołanie:

https://example.com/serve.php?file=zdjecie123.jpg

Przykład w Koseven Framework

Poniżej znajdziesz przykład bezpiecznego serwowania plików z użyciem frameworka Koseven (fork Kohana 3.3) oraz metody $response->send_file().

Scenariusz

Chcemy udostępnić użytkownikowi plik (np. zdjęcie lub PDF) tylko jeśli jest zalogowany. Pliki są przechowywane poza katalogiem DOCROOT, np. w APPPATH.'/uploads/'.

Przykład kontrolera: Controller_File

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_File extends Controller {

    public function action_view()
    {
        // 1. Autoryzacja użytkownika (przykład)
        if (!Auth::instance()->logged_in()) {
            throw HTTP_Exception::factory(403, 'Brak dostępu');
        }

        // 2. Pobierz nazwę pliku z GET lub segmentu URI
        $filename = basename($this->request->param('file')); // np. /file/view/plik.jpg

        // 3. Ścieżka do chronionego pliku
        $filepath = APPPATH.'uploads'.DIRECTORY_SEPARATOR.$filename;

        // 4. Sprawdzenie istnienia pliku
        if (!file_exists($filepath)) {
            throw HTTP_Exception::factory(404, 'Plik nie istnieje');
        }

        // 5. Opcjonalna walidacja uprawnień do danego pliku (np. czy użytkownik jest właścicielem)

        // 6. Serwowanie pliku jako inline (czyli do podglądu w przeglądarce, np. PDF lub obraz)
        $this->response->send_file($filepath, null, ['inline' => true]);

        // Uwaga: send_file automatycznie kończy wykonanie aplikacji
    }
}

Routing (w APPPATH/bootstrap.php lub routes.php)

Route::set('file.view', 'file/view/<file>')
    ->defaults([
        'controller' => 'file',
        'action'     => 'view',
    ]);

Przykładowy URL:

https://example.com/file/view/dokument.pdf

Uwagi dotyczące bezpieczeństwa

  • basename() chroni przed atakiem directory traversal (../../etc/passwd).
  • Jeśli potrzebujesz przechowywać pliki w strukturze podkatalogów, rozbuduj walidację ścieżki.
  • Można też zastosować token w URL-u, aby ograniczyć dostęp tymczasowo:

    file/view/plik.pdf?token=abc123

I sprawdzać token w bazie danych lub sesji.

Zalety send_file() w Koseven

  • Automatycznie ustawia nagłówki Content-Type, Content-Disposition i Content-Length.
  • Obsługuje zarówno inline, jak i attachment.
  • Obsługuje force-download i możliwość cache’owania przez przeglądarkę.

Zalety serwowania plików przez PHP

  1. Kontrola dostępu – można łatwo sprawdzić, czy użytkownik ma prawo do danego pliku.
  2. Logowanie dostępu – możliwość zapisywania, kto i kiedy pobrał dany plik.
  3. Ochrona lokalizacji plików – ścieżka do fizycznego pliku nie jest publiczna.
  4. Dynamiczne przetwarzanie – np. konwersja obrazów, znak wodny, optymalizacja przed wysłaniem.

Wady i problemy

  1. Niższa wydajność – PHP musi przetworzyć każde żądanie, co obciąża serwer bardziej niż serwowanie statyczne przez Apache/Nginx.
  2. Złożoność – dodatkowa warstwa logiki, która wymaga odpowiedniego zabezpieczenia.
  3. Problemy z cache’owaniem – trudniej zastosować mechanizmy CDN i cache przeglądarki.
  4. Potencjalne luki – nieprawidłowe filtrowanie nazw plików może prowadzić do ataków typu directory traversal (np. ../../../etc/passwd).

Dodatkowe metody zabezpieczeń

1. Pliki .htaccess (dla Apache)

W katalogu z plikami można dodać:

Deny from all

To uniemożliwia bezpośredni dostęp przez przeglądarkę.

2. Tokeny dostępu

Generowanie jednorazowych tokenów lub tymczasowych URL-i (np. z datą ważności).

3. Nagłówki referera

Ograniczenie dostępu tylko jeśli żądanie pochodzi z określonej strony (łatwe do obejścia, ale może być użyte jako dodatkowa warstwa).

Podsumowanie

Bezpieczne serwowanie plików to ważny aspekt każdej aplikacji webowej. Statyczne udostępnianie zasobów jest szybkie, ale nie daje kontroli nad tym, kto je pobiera. Dzięki użyciu PHP jako pośrednika można skutecznie ograniczyć dostęp do plików tylko dla uprawnionych użytkowników, choć kosztem wydajności i prostoty.

Dobrze zaprojektowany system serwowania plików powinien łączyć mechanizmy ochrony (autoryzacja, ograniczenie katalogów, walidacja nazw plików) z rozsądnym podejściem do wydajności — np. poprzez cachowanie czy użycie CDN dla mniej wrażliwych danych.

8 czerwca 2025 12

Kategorie

programowanie

Dziękujemy!
()

Powiązane wpisy


Informacja o cookies

Moja strona internetowa wykorzystuje wyłącznie niezbędne pliki cookies, które są wymagane do jej prawidłowego działania. Nie używam ciasteczek w celach marketingowych ani analitycznych. Korzystając z mojej strony, wyrażasz zgodę na stosowanie tych plików. Możesz dowiedzieć się więcej w mojej polityce prywatności.