Ich habe ein System (webbasierte Anwendung), das Dateianhänge von einem System eines Drittanbieters über SOAP abruft. Diese werden wiederum auf unserem System als Dateien in einem Verzeichnis erstellt.
Wenn ein Benutzer des Systems (authentifiziert durch ldap) eine Anfrage an meine Anwendung stellt, um einen dieser Anhänge abzurufen:
1. I request it via soap
2. Process the response to build the file on our system
3. Redirect user to the location so they can download the file.
Ist dies zunächst einmal ein guter Ansatz?
Gibt es eine bessere Möglichkeit, Dateien bereitzustellen, die sich nicht viel nach dem Herunterladen des Anhangs auf dem Server befinden (der Cron-Job bereinigt das Verzeichnis von Zeit zu Zeit)?
Zweitens, gibt es eine Möglichkeit, Dateien über Apache bereitzustellen, ohne sie im Webstamm zu speichern?
Drittens, wie erzwinge ich Berechtigungen für diese Dateien, damit nicht jeder Benutzer nur einen Anhang herunterladen kann?
Unser Setup:
linux
apache
php - soap libraries for communication
seperate LDAP for authentication
3rd party soap server (where attachments come from)
BEARBEITEN: Der Code für den Anhang, falls jemand neugierig ist.
<?php
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
//require global definitions
require_once("includes/globals.php");
//validate the user before continuing
isValidUser();
$subTitle = "Attachment";
$attachmentPath = "/var/www/html/DEVELOPMENT/serviceNow/selfService/uploads/";
if(isset($_GET['id']) and !empty($_GET['id'])){
//first lookup attachment meta information
$a = new Attachment();
$attachment = $a->get($_GET['id']);
//filename will be original file name with user name.n prepended
$fileName = $attachmentPath.$_SESSION['nameN'].'-'.$attachment->file_name;
//instantiate new attachmentDownload and query for attachment chunks
$a = new AttachmentDownload();
$chunks= $a->getRecords(array('sys_attachment'=>$_GET['id'], '__order_by'=>'position'));
$fh = fopen($fileName.'.gz','w');
// read and base64 encode file contents
foreach($chunks as $chunk){
fwrite($fh, base64_decode($chunk->data));
}
fclose($fh);
//open up filename for writing
$fh = fopen($fileName,'w');
//open up filename.gz for extraction
$zd = gzopen($fileName.'.gz', "r");
//iterate over file and write contents
while (!feof($zd)) {
fwrite($fh, gzread($zd, 60*57));
}
fclose($fh);
gzclose($zd);
unlink($fileName.'.gz');
$info = pathinfo($fileName);
header('Content-Description: File Transfer');
header('Content-Type: '.Mimetypes::get($info['extension']));
header('Content-Disposition: attachment; filename=' . basename($fileName));
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($fileName));
ob_clean();
flush();
readfile($fileName);
exit();
}else{
header("location: ".$links['status']."?".urlencode("item=incident&action=view&status=-1&place=".$links['home']));
}
?>
Antworten:
Hört sich gut an. Stellen Sie einfach sicher, dass Sie den Benutzer authentifizieren, bevor Sie dies alles durchgehen.
Legen Sie die Dateien außerhalb der Webroot ab. Übergeben Sie dann mit PHP die Datei durch ein Skript. Auf diese Weise kann niemand direkt auf die Datei verlinken und Ihre Steuerelemente umgehen. (Stellen Sie natürlich sicher, dass das Skript, das dies tut, erst nach Überprüfung des Benutzers über die Berechtigung zum Abrufen dieser Datei verfügt.)
Beispiel PHP:
Lassen Sie die Benutzer sich anmelden, um ihre Dateien abzurufen. Anschließend können Sie eine Sitzungsvariable festlegen, die angibt, dass sie heruntergeladen werden dürfen. Stellen Sie sicher, dass Ihre Skripte sie auf jeder Seite dieses Prozesses authentifizieren.
quelle