2012-05-24 7 views
8

Ich arbeite an der Entwicklung einer Website, die es Clients ermöglicht, sich einzuloggen und verschiedene auf dem Server gespeicherte PDFs zu sehen. Diese PDFs werden für den Client eindeutig sein und sollten nicht für jemanden zugänglich sein, der nicht eingeloggt ist. Das Abrufen der Dateien auf dem Server sollte kein Problem darstellen. Ich bin mir nicht sicher, wie ich sie den Endbenutzern bereitstellen soll.Erstellen eines sicheren Dateihostingservers für PDFs

Ich habe diese Art von Sache mit Daten von SQL servers anstelle von Dateien implementiert, so dass ich nicht ganz sicher bin, was der effektivste Weg, um darüber zu gehen.

Die Website ist auf einer LAMP und meine minimale Erfahrung ist in PHP (aber wenn ein Framework oder andere Sprache dies einfacher machen würde, kann ich es lernen).

Ich bin wahrscheinlich in meinem Kopf, aber ich bin normalerweise, also würde jede Eingabe großartig sein.

Antwort

9

Legen Sie die Dateien außerhalb der Webroot. Dann mit PHP übergeben Sie die Datei über ein Skript. Auf diese Weise kann niemand direkt mit der Datei verknüpfen und Ihre Steuerelemente umgehen. (Stellen Sie sicher, dass das Skript, das dies erst nach Überprüfung des Benutzers tut, die Berechtigung zum Abrufen dieser Datei hat).

Beispiel PHP:

<?php 
    session_start(); 
    if (!isset($_SESSION['authenticated'])) { 
     exit; 
    } 
    $file = '/path/to/file/outside/www/secret.pdf'; 

    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename=' . basename($file)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Pragma: public'); 
    header('Content-Length: ' . filesize($file)); 
    ob_clean(); 
    flush(); 
    readfile($file); 
    exit; 
?> 
+0

Sollte nicht 'session_start();' geladen werden? Ich nehme an, dass es mit Sitzungen arbeiten soll. –

+0

Eigentlich sollte es ja sein. Ich war so auf das Kernkonzept konzentriert, dass ich kein wirklich vollständiges Beispiel lieferte. Ich werde das jetzt beheben ... –

+0

Ich überprüfe einfach ;-) –

4

Der einfache Weg ist, diese Dateien lange zufällige Dateinamen zu geben (etwa 20 zufällige Zeichen). Technisch sind sie für jedermann zugänglich, aber es ist nicht möglich, die URL zu erraten, so dass nur autorisierte Personen Zugang haben.

Alternativ skizziert John Conde bereits eine Möglichkeit, eine Datei aus einem PHP-Skript zu bedienen. Es wird eine kleine Leistungseinbuße entstehen, aber so sicher wie Ihr Code ist. Die einzige Sache, die ich hinzufügen kann, ist, dass, wenn Sie sie nicht außerhalb von Webroot platzieren können, Sie .htaccess verwenden können, um zu verhindern, dass Leute direkt auf die Dateien zugreifen.

+1

Ich würde GUID vorschlagen. Das hat immer noch das Problem, dass ich den Server pingen kann, bis ich etwas Interessantes bekomme, obwohl man die Erfolgsaussichten verschwindend klein machen kann. Ich unterstütze die Verwendung von .htaccess, um den Zugriff auf den Ordner zu blockieren. – zebediah49

+1

@ zebediah49 - Es ist eine Möglichkeit, aber [es gibt Fallstricke] (http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx), die Sie beachten sollten. Einfach eine zufällige Zeichenfolge zu generieren ist sicherer. Und wenn Sie zu 110% sicher sein wollen, verwenden Sie einen kryptografisch starken Zufallszahlengenerator. –

+0

Sehr interessant, danke. Ich habe GUID für Länge ausgewählt, aber ich würde immer noch vermeiden, öffentlich zugängliche URLs zu verwenden, aber das ist ein sehr guter Punkt. – zebediah49

2

John hat die primäre korrekte Art und Weise, dies zu tun, geschrieben, also füge ich die (wahrscheinlich minderwertige) Alternative hinzu: Serve es aus der Datenbank. Haben Sie einfach eine BLOB-Spalte für das PDF und lesen/speichern Sie die Dateidaten aus der Datenbank. Sie werden mit einem ziemlich großen Tisch enden, aber es wird funktionieren. Um es zu bedienen, müssen Sie die gleichen header() s wie John gepostet, Sie senden nur die Daten aus der DB statt aus der Datei.

Dies hat den Vorteil, nicht Sie haben keine Dateinamen Kollisionen zu gewährleisten hat, usw.

Verwandte Themen