Beveiliging van bestanden (links)

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Jordy Heer

Jordy Heer

20/01/2015 20:18:21
Quote Anchor link
Hallo,

Waarschijnlijk zal het wel ergens bekend zijn, maar heb tot op heden nog geen goed script kunnen vinden.
Ik heb een website met waarbij een inlogprocedure aan vast zit.
Nu krijgen gebruikers bijvoorbeeld een download pagina waarin ze bestanden kunnen downloaden. (elke gebruikersgroep krijgt de links zichtbaar o.b.v. de user_role)

Echter nu wil ik hierop wat meer beveiliging zetten. Zodat de gebruiker die op de link klikt het bestand ook daadwerkelijk mag downloaden. Ieder elk ander bestand wat hij niet mag zien, mag hij ook niet downloaden.

Nu heb ik zelf ook al achterhaald, dat wanneer iemand de link van het bestand achterhaald, en niet ingelogd is het bestand ook kan downloaden. Wil dus dit dicht hebben, zodat er geen bestanden gedownload kunnen worden door bezoekers & gebruikers waar zij geen recht op hebben.

Heeft iemand een script of kan iemand mij hier bij assisteren?
Gewijzigd op 20/01/2015 20:19:14 door Jordy Heer
 
PHP hulp

PHP hulp

29/04/2024 08:19:56
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 20:24:57
Quote Anchor link
Koppel het bestand via een tabel in de database aan de user die het mag downloaden?

Zet de bestanden uiteraard buiten de webroot, en haal ze met readfile () en de juiste headers op.
 
Jordy Heer

Jordy Heer

20/01/2015 20:34:03
Quote Anchor link
1. Database koppeling bestand
Ik heb een tabel genaamd "downloads" waarin ik alle info heb staan van het bestand om de <a> link te creëren. (path,file_name).
Per record staat de user_group die recht zou mogen hebben tot dit bestand. Hier wordt al door bepaald of de user de link mag zien op de pagina

2. De bestanden heb ik nu buiten de "public_html" folder gezet

3. Ophalen met readfile() en juiste headers. Hoe kan ik dat het beste doen? op de downloads.php pagina wordt de <a> </a> gecreëerd met if statements en dan een echo.

Hoor ook graag of punt 1 en 2 ook correct zijn.
Gewijzigd op 20/01/2015 20:34:53 door Jordy Heer
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 20:47:53
Quote Anchor link
Elke download heeft vast een eigen unieke ID of naam. Dus via GET kan je het juiste bestand ophalen na de readfile (). Er kan geen HTML-output vooraf wrden geplaatst omdat er een header voor hoort.

Daarna vind de user-check plaats.
Gewijzigd op 20/01/2015 20:49:55 door - Ariën -
 
Jordy Heer

Jordy Heer

20/01/2015 20:54:43
Quote Anchor link
Ik volg je even niet.

Situatie nu:

table downloads:
ID: 1
path media/uploads/nl/fileuploads/
file: bestand.pdf
titl: Titel
display: Weergave
user_rol: rechtengroep
active_flag: link_actief? (1/0)
target_blank: moet er een target_blank uitgevoerd worden (1/0)
file_type: type bestand (pdf,doc,xls etc)

downloads.php
bouwt de <a> </a> op vanuit de bovenstaande informatie o.b.v. de user_role.


Hoe bouw ik dan de readfile & GET in de downloads.php o.b.v. de user_role ?
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 20:59:37
Quote Anchor link
Heb je een dumpje van je database structuur met enkele records. Dan heb ik beter inzicht.
 
Jordy Heer

Jordy Heer

20/01/2015 21:00:29
Quote Anchor link
subject size order_by path file title display user_role active_flag target_blank file_type
document 3,3 Mb 1 media/uploads/nl/fileuploads/ aktevansplitsing.pdf Akte van Splitsing Akte van Splitsing 0 1 1 pdf
document 99 Kb 2 media/uploads/nl/fileuploads/ huishoudelijkreglement.pdf Huishoudelijkreglement Huishoudelijkreglement 0 1 1 pdf
document 64 Kb 3 media/uploads/nl/fileuploads/ bouwprocedure.pdf Bouwprocedure Bouwprocedure 0 1 1 pdf

Toevoeging op 20/01/2015 21:03:46:

Volgens mij is het niet echt leesbaar met records: maar dit is sowieso de structuur.

Field Type Null Key Default Extra
subject varchar(200) YES NULL
size varchar(20) YES NULL
order_by int(11) NO PRI NULL auto_increment
path varchar(500) YES NULL
file varchar(200) YES NULL
title varchar(200) YES NULL
display varchar(200) YES NULL
user_role int(11) YES 1
active_flag int(11) YES 0
target_blank int(11) YES 0
file_type varchar(200) YES NULL

order by is het id
Gewijzigd op 20/01/2015 21:04:25 door Jordy Heer
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 21:06:09
Quote Anchor link
Gelukkig hebben we hier codetags en kan je met phpMyAdmin een mooie export maken.
 
Jordy Heer

Jordy Heer

20/01/2015 21:09:58
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
"subject","size","order_by","path","file","title","display","user_role","active_flag","target_blank","file_type"
"document","3,3 Mb","1","media/uploads/nl/fileuploads/","aktevansplitsing.pdf","Akte van Splitsing","Akte van Splitsing","0","1","1","pdf"
"document","99 Kb","2","media/uploads/nl/fileuploads/","huishoudelijkreglement.pdf","Huishoudelijkreglement ","Huishoudelijkreglement ","0","1","1","pdf"
"document","64 Kb","3","media/uploads/nl/fileuploads/","bouwprocedure.pdf","Bouwprocedure","Bouwprocedure","0","1","1","pdf"
Gewijzigd op 20/01/2015 21:12:25 door - Ariën -
 
Peter  Flos

Peter Flos

20/01/2015 21:11:40
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
// Sessie Starten
session_start();

// Connectie Includen
include 'connection.php';

// Variabelen opmaken. Je kunt de variabelen ook direct in de query zetten
$file = mysqli_real_escape_string($con,$_GET['file']);
$role = mysqli_real_escape_string($con,$_SESSION['role']);

// Controleren of de gebruiker bij het bestand de juiste rechten heeft
$count = mysqli_num_rows(mysqli_query($con,"SELECT order_by FROM downloads WHERE file = '$file' AND user_role = '$role'"));

// User-Output aan de hand van $count
// Bestand en Rol zijn juist? Bestand downloaden

if($count == '1'){
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}

// Bij onjuist geven we een foutmelding
else{
echo "U bent niet bevoegd dit bestand te downloaden.";
}
}

?>


Edit: Paar fouten eruit gehaald.
Gewijzigd op 20/01/2015 21:12:57 door Peter Flos
 
Jordy Heer

Jordy Heer

20/01/2015 21:26:25
Quote Anchor link
Kom er nog niet helemaal uit.
Heb deze nu in een download_check.php bestand gezet.
Als ik deze benader met bv download_check.php?file=aktevansplitsing.pdf krijg ik nog allerlei foutmeldingen.

Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in public_html/download_check.php on line 9

Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in public_html/download_check.php on line 10

Warning: mysqli_query() expects parameter 1 to be mysqli, null given in public_html/download_check.php on line 13

Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, null given in public_html/download_check.php on line 13
Gewijzigd op 20/01/2015 23:01:42 door Jordy Heer
 
Peter  Flos

Peter Flos

20/01/2015 21:29:30
Quote Anchor link
Gebruik je mysql of mysqli? Je moet in elk geval de volgende connectie hebben, maar dan met jouw gegevens:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
$con
= mysqli_connect("localhost","xxxx","xxxx","xxxx");

// Check connectie
if (mysqli_connect_errno())
  {

  echo "Connectiefout: " . mysqli_connect_error();
  exit;
  }

?>
 
Jordy Heer

Jordy Heer

20/01/2015 21:30:26
Quote Anchor link
Volgens mij mysql :-)
 
Peter  Flos

Peter Flos

20/01/2015 21:32:28
Quote Anchor link
Om je even op de hoogte te brengen gaat mysql eruit en zal je deze later niet meer in een nieuwere versie van PHP kunnen gebruiken. Ik raad je dan ook aan om over te stappen.

Mysql heeft geen 2e parameter nodig bij een real escape. Ik zit al een tijdje in de mysqli, dus hoop dat het zo goed gaat:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
// Sessie Starten
session_start();

// Connectie Includen
include 'connection.php';

// Variabelen opmaken. Je kunt de variabelen ook direct in de query zetten
$file = mysql_real_escape_string($_GET['file']);
$role = mysql_real_escape_string($_SESSION['role']);

// Controleren of de gebruiker bij het bestand de juiste rechten heeft
$count = mysql_num_rows(mysql_query("SELECT order_by FROM downloads WHERE file = '$file' AND user_role = '$role'"));

// User-Output aan de hand van $count
// Bestand en Rol zijn juist? Bestand downloaden

if($count == '1'){
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}

// Bij onjuist geven we een foutmelding
else{
echo "U bent niet bevoegd dit bestand te downloaden.";
}
}

?>
Gewijzigd op 20/01/2015 21:32:52 door Peter Flos
 
Jordy Heer

Jordy Heer

20/01/2015 21:39:00
Quote Anchor link
ok stapje verder.
Krijg nu U bent niet bevoegd dit bestand te downloaden
maar $count is wel 1

Mis ik niet nog het pad van de locatie waar het bestand staat?
of moet die in $file zitten?
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 21:39:08
Quote Anchor link
Neemt niet weg dat er nog goede fout-afhandeling aan de queries moet worden toegevoegd. Elke query kan ooit eens stuk gaan bij de uitvoer.

Het kan nog netter met een mooie functie en een DEBUG-'switch', maar ik houd het even simpel.

Verder heb ik de bestandnaam toegevoegd en de count check verbeterd.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
// VANAF LIJN 12!!!

// query opslaan in een result en uitvoeren

$result = mysql_query("SELECT order_by FROM downloads WHERE file = '$file' AND user_role = '$role'");
if($result) {
    // resultaat van query in een array zetten.
    $data = mysql_fetch_assoc($result);
    // Controleren of de gebruiker bij het bestand de juiste rechten heeft
    $count = mysql_num_rows($result);
    $file = $data['file']; // 'file' is veldnaam uit de tabel.

    // User-Output aan de hand van $count
    // Bestand en Rol zijn juist? Bestand downloaden

    if($count == 1){
        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            readfile($file);
           exit;
        }
else {
            // Bij onjuist geven we een foutmelding
            echo "U bent niet bevoegd dit bestand te downloaden.";
        }
    }
}
else {
    // Als de query stuk is of niet uitgevoerd kan worden tonen we een foutmelding.
    echo "Er is een fout opgetreden in de query: ".mysql_error();
}

?>
Gewijzigd op 20/01/2015 21:44:16 door - Ariën -
 
Peter  Flos

Peter Flos

20/01/2015 21:46:48
Quote Anchor link
Ik heb inderdaad een foutje gemaakt. Hierbij het verbeterde script van Aar:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
// VANAF LIJN 12!!!

// query opslaan in een result en uitvoeren

$result = mysql_query("SELECT file FROM downloads WHERE file = '$file' AND user_role = '$role'");
if($result) {
    // resultaat van query in een array zetten.
    $data = mysql_fetch_assoc($result);
    // Controleren of de gebruiker bij het bestand de juiste rechten heeft
    $count = mysql_num_rows($result);
    $file = $data['file']; // 'file' is veldnaam uit de tabel.

    // User-Output aan de hand van $count
    // Bestand en Rol zijn juist? Bestand downloaden

    if($count == 1){
        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            readfile($file);
           exit;
        }

    echo "Het bestand is niet gevonden.";
    }
else {
            // Bij onjuist geven we een foutmelding
            echo "U bent niet bevoegd dit bestand te downloaden.";
    }
}
else {
    // Als de query stuk is of niet uitgevoerd kan worden tonen we een foutmelding.
    echo "Er is een fout opgetreden in de query: ".mysql_error();
}

?>


Edit: En nog een extra foutafhandelingetje toegevoegd
Edit 2: Nog een kleine fout in de select eruit gehaald.
Gewijzigd op 20/01/2015 21:48:40 door Peter Flos
 
Jordy Heer

Jordy Heer

20/01/2015 21:49:40
Quote Anchor link
dank jullie wel!
Krijg nu inderdaad dat het bestand niet is gevonden, volgens mij mis ik nu nog het pad van waar het bestand staat (buiten de root)
Waar moet die inkomen?
 
Peter  Flos

Peter Flos

20/01/2015 21:53:15
Quote Anchor link
Bestanden zet je buiten de public html.
Je krijgt dus:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
- ROOT
(in je root)
---- bestand1.pdf
---- bestand2.pdf
---- bestand3.pdf
---- public_html
(in je public_html)
------- index.php
------- download_check.php


Download_check.php staat in dit geval in je public_html. 1 map terug staat je root en je bestanden.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
header('Content-Disposition: attachment; filename=../'.$file);


Nu heb ik het zelf niet getest, maar ../ zorgt ervoor dat je 1 map terug gaat.
Gewijzigd op 20/01/2015 21:57:00 door Peter Flos
 
- Ariën  -
Beheerder

- Ariën -

20/01/2015 21:54:07
Quote Anchor link
Die staat in de database, in het 'file'-veld. Je moet wel even het pad naar die directory in $file plaatsen.

@peter, is het niet handig om het pad in $file te plaatsen? Anders snapt filesize, en file_exists het ook niet meer helemaal ;-)
Gewijzigd op 20/01/2015 21:58:46 door - Ariën -
 
Jordy Heer

Jordy Heer

20/01/2015 22:00:25
Quote Anchor link
heb nu header('Content-Disposition: attachment; filename= ../fileuploads/'.basename($file));
maar nog steeds bestand niet gevonden
 

Pagina: 1 2 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.