Protejarea accesului direct la PDF și ZIP doar pentru utilizatorii autentificați (fără plugin)
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 — 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 );
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.

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?

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.

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!

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.

@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?
