Protejarea accesului direct la PDF și ZIP doar pentru utilizatorii autentificați (fără plugin)

29 sept. 2017, 20:54:38
Vizualizări: 13.6K
Voturi: 6

Lucrez la un site de suport WordPress care are conținut accesibil doar pentru utilizatorii înregistrați, inclusiv fișiere PDF și ZIP încărcate.

Caut o metodă de a preveni accesul direct la aceste fișiere PDF și ZIP din directorul wp-content/uploads fără a utiliza un plugin.

Citind întrebări mai vechi, aceasta este FOARTE apropiată (dar comentariile sunt închise): https://wordpress.stackexchange.com/a/37743/18608 deoarece detectează accesul direct la fișier, apoi efectuează o verificare pentru a salva fișierul solicitat și verifică dacă utilizatorul este autentificat. Dacă nu este, acesta este redirecționat către pagina de autentificare WordPress. Dacă este autentificat, atunci încarcă fișierul.

Acesta este htaccess-ul original:

RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]

Totuși, scriptul blochează accesul la TOATE fișierele din directorul wp-content/uploads, inclusiv imaginile - deci, dacă utilizatorul nu este autentificat, chiar și imaginile din articole (care nu trebuie protejate) sunt ascunde pe front-end.

Încerc să modific RewriteRule pentru a verifica DOAR fișierele PDF sau ZIP, astfel încât fișierul dl-file.php să fie apelat doar dacă se solicită un PDF sau ZIP.

Am încercat următoarele, dar returnează "404-File not found." când se accesează un PDF sau ZIP când utilizatorul este autentificat, deși verificarea tipului de fișier pare să funcționeze, verificarea dl-file.php eșuează.

RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([^/]*\.(pdf|zip))$ filecheck.php?file=$1 [QSA,L]

Cum aș putea modifica acest lucru, astfel încât să apeleze dl-file.php doar dacă se solicită un fișier pdf sau zip, dar să transmită în continuare informațiile corecte către dl-file.php?

Mulțumesc, Jonathon

/*
 * dl-file.php
 *
 * Protejează fișierele încărcate cu autentificare.
 * 
 * @link http://wordpress.stackexchange.com/questions/37144/protect-wordpress-uploads-if-user-is-not-logged-in
 * 
 * @author hakre <http://hakre.wordpress.com/>
 * @license GPL-3.0+
 * @registry SPDX
 */

require_once('wp-load.php');

is_user_logged_in() || auth_redirect();

list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL);

$file =  rtrim($basedir,'/').'/'.str_replace('..', '', isset($_GET[ 'file' ])?$_GET[ 'file' ]:'');
if (!$basedir || !is_file($file)) {
    status_header(404);
    die('404 &#8212; Fișierul nu a fost găsit.');
}

$mime = wp_check_filetype($file);
if( false === $mime[ 'type' ] && function_exists( 'mime_content_type' ) )
    $mime[ 'type' ] = mime_content_type( $file );

if( $mime[ 'type' ] )
    $mimetype = $mime[ 'type' ];
else
    $mimetype = 'image/' . substr( $file, strrpos( $file, '.' ) + 1 );

header( 'Content-Type: ' . $mimetype ); // trimite întotdeauna acest header
if ( false === strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) )
    header( 'Content-Length: ' . filesize( $file ) );

$last_modified = gmdate( 'D, d M Y H:i:s', filemtime( $file ) );
$etag = '"' . md5( $last_modified ) . '"';
header( "Last-Modified: $last_modified GMT" );
header( 'ETag: ' . $etag );
header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 100000000 ) . ' GMT' );

// Suport pentru Conditional GET
$client_etag = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) : false;

if( ! isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )
    $_SERVER['HTTP_IF_MODIFIED_SINCE'] = false;

$client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
// Dacă șirul este gol, returnează 0. Dacă nu, încearcă să-l parsezi într-un timestamp
$client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;

// Crează un timestamp pentru cea mai recentă modificare...
$modified_timestamp = strtotime($last_modified);

if ( ( $client_last_modified && $client_etag )
    ? ( ( $client_modified_timestamp >= $modified_timestamp) && ( $client_etag == $etag ) )
    : ( ( $client_modified_timestamp >= $modified_timestamp) || ( $client_etag == $etag ) )
    ) {
    status_header( 304 );
    exit;
}

// Dacă am ajuns până aici, trimite fișierul
readfile( $file );
4
Comentarii

Rețineți că dacă puneți acest comentariu în partea de sus a răspunsului /** Plugin Name: Zip Plugin **/ acesta devine un plugin, dar ceea ce întrebați pare să nu aibă nicio legătură cu WordPress, fiind o întrebare pură despre Apache HTAccess

Tom J Nowell Tom J Nowell
29 sept. 2017 21:45:01

Mulțumesc - postarea originală la care mă refeream conține dl-file.php cu verificarea autentificării/redirecționare care este specifică WordPress - cu asta am probleme să o fac să funcționeze. Încerc să verific pentru pdf și zip, și încă nu reușesc să fac verificarea condițională a autentificării să funcționeze pentru partea de redirecționare. Am adăugat mai multe detalii pentru claritate.

d38 d38
29 sept. 2017 22:47:45

Tocmai am observat, ai schimbat dl-file.php în filecheck.php? Presupun că acesta este același fișier?

MrWhite MrWhite
30 sept. 2017 00:54:45

Mulțumesc, este - am schimbat-o aici, dar am păstrat-o la fel pentru exemplu. Mi-a scăpat referința la ea.

d38 d38
30 sept. 2017 01:16:15
Toate răspunsurile la întrebare 1
6
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([^/]*\.(pdf|zip))$ filecheck.php?file=$1 [QSA,L]

Acest cod pare corect, cu excepția cazului în care aveți subdirectoare suplimentare în directorul /uploads? O alternativă este să adăugați o condiție suplimentară la regula originală care să rescrie cererea doar dacă se termină cu .pdf sau .zip. De exemplu:

RewriteCond %{REQUEST_URI} \.(pdf|zip)$ [NC]
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]

Nu ar trebui să conteze prea mult, dar asigurați-vă că această regulă este plasată înainte de front-controller-ul WordPress.

30 sept. 2017 00:26:22
Comentarii

Mulțumesc - are sens. Testez aici, dar din anumite motive nu detectează condiția de autentificare, așa că PDF-ul se încarcă când sunt deconectat?

d38 d38
30 sept. 2017 01:18:28

Mulțumesc, MrWhite - aceasta a fost direcția corectă. Nu am reușit să fac REQUEST_URL să funcționeze în prima RewriteCond, dar schimbarea în RewriteCond %{REQUEST_FILENAME} .(pdf|zip)$ a funcționat.

d38 d38
30 sept. 2017 02:32:49

Aaa, scuze, a fost o greșeală de tipar, ar fi trebuit să fie REQUEST_URI, nu REQUEST_URL! (Am actualizat răspunsul meu.) Mă bucur că ai reușit să funcționeze!

MrWhite MrWhite
30 sept. 2017 02:45:39

Salut, Mulțumesc pentru trucul tău. Am o întrebare: dacă nu sunt autentificat, sunt redirecționat către pagina de login când introduc o adresă URL cu un fișier PDF în browser. Este posibil să fiu redirecționat către pagina 404? Mulțumesc din nou.

Samuel Samuel
26 apr. 2019 12:01:05

@sampaii Ar trebui să faci asta în scriptul tău de descărcare/autentificare (în PHP)... dacă utilizatorul nu este autentificat, atunci răspunde cu o eroare 404 în loc să redirecționezi - ceea ce probabil este declanșat acum de scriptul tău - dacă ai urmat exemplul de mai sus?

MrWhite MrWhite
26 apr. 2019 12:59:32

mrwhite, îmi pare rău că abia acum văd mesajul tău. este o problemă cu această metodă. când mă autentific în backend și introduc URL-ul oricărui fișier PDF, sunt redirecționat către pagina 404. ai vreo idee, te rog?

Samuel Samuel
12 mai 2020 16:22:28
Arată celelalte 1 comentarii