Come proteggere i file caricati se l'utente non ha effettuato l'accesso?

22 dic 2011, 18:46:18
Visualizzazioni: 88.3K
Voti: 107

Uso WordPress per un sito privato dove gli utenti caricano file. Utilizzo il plugin "Private WordPress" per impedire l'accesso al sito se l'utente non ha effettuato il login.

Vorrei fare lo stesso con i file caricati nella cartella uploads.

Quindi se un utente non ha effettuato l'accesso non dovrebbe poter accedere a: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf se provano ad accedere ma non sono loggati dovrebbero essere reindirizzati alla pagina di login ad esempio.

Ho trovato un plugin chiamato private files ma l'ultimo aggiornamento risale al 2009 e non sembra funzionare sul mio WordPress.

Qualcuno conosce un metodo? Il metodo hotlinking sarà sufficiente per proteggere questo?

Ho trovato anche questo metodo:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^.*uploads/private/.*
RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in.*$ [NC]
RewriteRule . /index.php [R,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Ma in questo caso qualsiasi utente che replica il cookie potrebbe bypassare questa protezione, giusto? Saluti

3
Commenti

Qualche motivo per cui non puoi usare una directory di upload diversa, come una al di fuori della root del sito?

onetrickpony onetrickpony
22 dic 2011 19:11:33

Non proprio, ma ho già tantissimi file allegati ai post in quella directory, non mi dispiacerebbe spostarli tutti se riesco a trovare una soluzione adeguata

chifliiiii chifliiiii
22 dic 2011 19:37:52

Nel caso tu reindirizzi automaticamente gli utenti alla schermata di login, un modo semplice per proteggere gli upload è controllare il referrer. Se il referrer è vuoto (accesso diretto) o diverso dal dominio in cui ospiti i file, allora lo blocchi.

Konstantinos Konstantinos
31 gen 2020 19:55:38
Tutte le risposte alla domanda 4
11
113

Verificare solo l'esistenza del cookie non costituisce una protezione particolarmente rigorosa.

Per ottenere una protezione più forte, puoi instradare o "proxare" tutte le richieste alla cartella degli upload (nell'esempio seguente uploads) attraverso uno script PHP:

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

Tutte le richieste ai file caricati (comprese le immagini nei post) verranno indirizzate a dl-file.php che potrà verificare se l'utente è loggato o meno.

Se l'utente non è loggato, verrà mostrato il form di login del sito. Dopo il login, l'utente verrà reindirizzato al file e potrà scaricarlo.

Esempio di dl-file.php.

Qualcosa di simile si trova in \wp-includes\ms-files.php nella tua installazione WordPress, ma è pensato per il multisito e senza il controllo del login e i reindirizzamenti.

A seconda del traffico che hai, potrebbe essere consigliabile integrare meglio questa soluzione con il tuo server, ad esempio utilizzando gli header X-Accel-Redirect o X-Sendfile.

2 gen 2012 23:50:59
Commenti

come si modifica dl-file.php se voglio memorizzare i file in una sottocartella come wp-content/uploads/secure ?

User User
12 gen 2012 00:54:57

Questa è l'unica soluzione veramente sicura. Tutto ciò che puoi trovare sul web, come controllare l'header referer, controllare i cookie, disabilitare la visualizzazione delle directory, è una mezza misura poiché è facile falsificare gli header delle richieste HTTP per aggirarla.

Lukasz Lukasz
20 set 2013 11:58:28

Ragazzi...questa sembrava la soluzione perfetta per me...il problema è che sto usando PDFJS di Mozilla per accedere ad alcuni PDF dalla cartella upload, e PDFJS utilizza header partial-content per ottenere solo le pagine che gli interessano...quindi questa soluzione non è praticabile per me.

qualche suggerimento??

Otto Nascarella Otto Nascarella
28 nov 2014 19:24:06

@OttoNascarella: Le richieste di contenuto parziale a PHP sono state risolte a partire da oggi, questo è indipendente da questa domanda su WordPress. Infatti, la domanda è piuttosto vecchia: Download riprendibili quando si usa PHP per inviare il file?

hakre hakre
5 dic 2014 12:17:49

@hakre E per alcune di quelle immagini usate nella homepage del sito quando un utente visita il sito?

Mi dà un errore 404 se non sono loggato.

Dhaval Panchal Dhaval Panchal
1 mag 2018 11:30:58

Qualcuno potrebbe spiegare questa riga di codice list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL); e in cosa differisce da $basedir = wp_upload_dir()['basedir']

Tomas Eklund Tomas Eklund
2 apr 2020 14:02:30

@TomasEklund: Il tuo è probabilmente meno complicato. Un motivo per quello originale è molto probabilmente la compatibilità con le versioni precedenti di PHP.

hakre hakre
4 apr 2020 17:08:42

Fantastico. Qualcuno potrebbe per favore trasformare questa soluzione in un plugin per Wordpress?

Jian Chen Jian Chen
17 mag 2020 07:17:34

Nota a margine: funziona con Wordpress 5.6.

long long
4 mar 2021 15:17:33

Nella mia configurazione Multisite, ho avuto problemi a popolare la posizione del file con il codice fornito. Questa soluzione ha funzionato meglio: $file = rtrim( DIR, '/' ) . $_SERVER['REQUEST_URI'];

Talha Imam Talha Imam
29 lug 2021 22:40:29

Per nginx nel file di configurazione del sito, all'interno del blocco server{}, ho aggiunto quanto segue per farlo funzionare: location /wp-content/uploads/ { rewrite ^/wp-content/uploads/(.*)$ /dl-file.php?file=$1 last; }

hax2024 hax2024
12 apr 2022 00:23:31
Mostra i restanti 6 commenti
4
21

Due modi, semplice in 2. con l'aiuto di una regola apache o in 1. con l'aiuto di codice personalizzato in un plugin.

1. Plugin

Puoi scrivere un plugin utilizzando l'hook init e il valore get $_GET[ 'file' ];. Se l'utente ha questo valore get, salta in una funzione per controllare i diritti di accesso ai file: Ad esempio, con una checkbox all'interno di una Meta Box.

add_action( 'init', 'fb_init' );
function fb_init() {
    // questo in una funzione per l'hook init
    if ( '' != $_GET[ 'file' ] ) {
        fb_get_file( $_GET[ 'file' ] );
    }
}

la funzione fb_get_file()

function fb_get_file( $file ) {

    $upload     = wp_upload_dir();
    $the_file   = $file; 
    $file       = $upload[ 'basedir' ] . '/' . $file;
    if ( !is_file( $file ) ) {
        status_header( 404 );
        die( '404 &#8212; File non trovato.' );
    }
    else {
        $image = get_posts( array( 'post_type' => 'attachment', 'meta_query' => array( array( 'key' => '_wp_attached_file', 'value' => $the_file ) ) ) );
        if ( 0 < count( $image ) && 0 < $image[0] -> post_parent ) { // allegato trovato e genitore disponibile
            if ( post_password_required( $image[0] -> post_parent ) ) { // password per il post non disponibile
                wp_die( get_the_password_form() );// mostra il form della password 
            }
            $status = get_post_meta( $image[0] -> post_parent, '_inpsyde_protect_content', true );

            if ( 1 == $status &&  !is_user_logged_in() ) {
                wp_redirect( wp_login_url( $upload[ 'baseurl' ] . '/' . $the_file ) );
                die();
            }
        }
        else {
            // non un allegato normale, controlla per la miniatura
            $filename   = pathinfo( $the_file );
            $images     = get_posts( array( 'post_type' => 'attachment', 'meta_query' => array( array( 'key' => '_wp_attachment_metadata', 'compare' => 'LIKE', 'value' => $filename[ 'filename' ] . '.' . $filename[ 'extension' ] ) ) ) );
            if ( 0 < count( $images ) ) {
                foreach ( $images as $SINGLEimage ) {
                    $meta = wp_get_attachment_metadata( $SINGLEimage -> ID );
                    if ( 0 < count( $meta[ 'sizes' ] ) ) {
                        $filepath   = pathinfo( $meta[ 'file' ] );
                        if ( $filepath[ 'dirname' ] == $filename[ 'dirname' ] ) {// percorso corrente della miniatura
                            foreach ( $meta[ 'sizes' ] as $SINGLEsize ) {
                                if ( $filename[ 'filename' ] . '.' . $filename[ 'extension' ] == $SINGLEsize[ 'file' ] ) {
                                    if ( post_password_required( $SINGLEimage -> post_parent ) ) { // password per il post non disponibile
                                        wp_die( get_the_password_form() );// mostra il form della password 
                                    }
                                    die('dD');
                                    $status = get_post_meta( $SINGLEimage -> post_parent, '_inpsyde_protect_content', true );

                                    if ( 1 == $status &&  !is_user_logged_in() ) {
                                        wp_redirect( wp_login_url( $upload[ 'baseurl' ] . '/' . $the_file ) );
                                        die();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $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 ); // sempre invia questo
    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' );

    // Supporto per 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'] );
    // Se la stringa è vuota, restituisce 0. Altrimenti, tenta di analizzarla in un timestamp
    $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;

    // Crea un timestamp per la nostra modifica più recente...
    $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;
    }

    // Se siamo arrivati fin qui, serviamo semplicemente il file
    readfile( $file );
    die();
}

Puoi anche aggiungere un URL personalizzato per i file tramite l'hook generate_rewrite_rules

add_filter( 'generate_rewrite_rules', 'fb_generate_rewrite_rules' );

function fb_generate_rewrite_rules( $wprewrite ) {
        $upload = wp_upload_dir();
        $path = str_replace( site_url( '/' ), '', $upload[ 'baseurl' ] );
        $wprewrite -> non_wp_rules = array( $path . '/(.*)' => 'index.php?file=$1' );
        return $wprewrite;
}

2. Controllo Apache per il Cookie

Lascia un nuovo file .htaccess all'interno della directory /wp-content/uploads/. O un'altra directory definita per gli upload.

Come funziona

All'interno dei container <IfModule>, ci sono tre regole che fanno quanto segue:

  1. Controlla se la richiesta è per qualsiasi file
  2. Controlla l'assenza di un cookie che inizia con wordpress_logged_in_
  3. Se queste condizioni sono soddisfatte, la richiesta del file sarà negata tramite risposta 403 "Forbidden"

Il trucco qui è il passaggio 2, quindi controlla l'assenza di un cookie che inizia con wordpress_logged_in_. Quando l'utente è loggato, WordPress aggiunge un cookie al tuo browser che assomiglia a:

wordpress_logged_in_1234567890abcdefghijklmnopqrstuvwxyz

Esempio di regola con un controllo per il tipo di file

# richiede il login per i file media
<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_FILENAME} (.*)
    RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_([a-zA-Z0-9_]*) [NC]
    RewriteRule .* - [F,L]
</IfModule>
3 gen 2012 12:20:25
Commenti

Non ha funzionato nel mio caso, qualcuno sa perché? Ho copiato esattamente.

Ryan S Ryan S
17 feb 2014 12:40:26

La protezione funziona solo per i PDF. Le altre estensioni di file non funzionano come: doc, docx, jpg ecc...

Patel Patel
23 ago 2017 13:43:48

L'opzione 2 ha funzionato perfettamente per tutti i tipi di file, grazie.

crdunst crdunst
5 mar 2021 18:23:21

Perché il condizionale per la dimensione del file per IIS?

Scribblemacher Scribblemacher
11 mar 2025 13:34:09
1

Se preferisci un approccio basato su plugin per risolvere questo problema, ecco una soluzione ragionevolmente buona che ho (finalmente) trovato:

  1. Installa il plugin 'Download Monitor', disponibile su:
    https://wordpress.org/plugins/download-monitor/
  2. Nella Dashboard di WordPress, vai alla nuova voce di menu 'Downloads' e aggiungi un nuovo 'Download', come descritto nella documentazione del plugin qui: https://www.download-monitor.com/kb/adding-downloads/. Prendi nota dello shortcode 'Download' fornito (ad esempio salvalo in Notepad). Nota che il file viene salvato in /wp-content/uploads/dlm_uploads/
  3. Nella metabox 'Download options', specifica 'Members only' (come documentato qui https://www.download-monitor.com/kb/download-options/), e clicca 'Publish'.
  4. Nella pagina in cui vuoi che appaia il download riservato ai membri, inserisci lo shortcode che hai annotato nel passaggio #2, e 'Pubblica/Aggiorna' la pagina, come documentato qui: https://www.download-monitor.com/kb/shortcode-download/. Puoi modificare il template del link di download come descritto qui https://www.download-monitor.com/kb/content-templates/, o crearne uno tuo (ad esempio per rimuovere il conteggio dei download)
  5. Naviga sulla tua pagina, dovresti vedere un link per il download (ma che non rivela l'URL del file). Se accedi alla stessa pagina in una nuova finestra del browser (o in modalità Incognito), dovresti scoprire che il download non funziona più.

Ciò significa che chiunque non sia loggato non può né scaricare il file né vedere il vero URL del file. Nel caso in cui qualcuno non autorizzato scoprisse l'URL del file, il plugin blocca anche l'accesso alla cartella /wp-content/uploads/dlm_uploads/ impedendo la navigazione diretta al file.

Bonus: se stai implementando questo per un sito in cui gli utenti devono poter accedere solo come 'Membri' (senza permessi WordPress come la modifica delle pagine o essere Admin), installa il plugin 'Members' https://wordpress.org/plugins/members/, crea un nuovo ruolo utente chiamato 'Member', e assegnagli solo la capacità 'read', crea un nuovo utente in WordPress, e assicurati di assegnargli il ruolo 'Member'.

Se vuoi proteggere il contenuto delle pagine, il plugin 'Members' offre alcune opzioni, oppure ci sono altri plugin disponibili. Se vuoi personalizzare la pagina di login per i Membri in modo che sia più accattivante del form di login predefinito di WordPress, usa qualcosa come 'Theme My Login': https://wordpress.org/plugins/theme-my-login/

13 apr 2017 12:09:36
Commenti

Il processo che ho descritto sopra è spiegato anche qui, anche se come puoi vedere non deve essere specifico solo per i PDF: http://www.thedigitalcrowd.com/website-development/wordpress/wordpress-restrict-access-to-pdf-downloads-with-private-members-login-details/

Matty J Matty J
13 apr 2017 12:11:01
0

Che ne dici di un approccio basato su plugin per risolvere questo problema? Ho trovato un plugin per WordPress creato proprio per questo:

Prevenire l'accesso a file/cartelle: https://wordpress.org/plugins/prevent-file-access/

8 gen 2021 16:28:32