Come proteggere i caricamenti, se l'utente non è connesso?


80

Uso wordpress per un sito privato in cui gli utenti caricano file. Uso "WordPress privato" per impedire l'accesso al sito se l'utente non ha effettuato l'accesso.

Vorrei fare lo stesso con i file caricati nella cartella dei caricamenti.

Pertanto, se un utente non ha effettuato l'accesso, non sarà in grado di accedere a: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf se tentano di accedere ma non sono connessi, quindi dovrebbero essere reindirizzato alla pagina di accesso, ad esempio.

Ho trovato un plug-in chiamato file privati ​​ma l'ultima volta è stato aggiornato nel 2009 e non sembra funzionare sul mio wordpress.

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

Ho anche trovato 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 allora qualsiasi utente che replica il cookie potrebbe passare questo diritto? Saluti


1
Qual è il motivo per cui non è possibile utilizzare una directory di caricamento diversa, come una fuori dalla radice del sito?
onetrickpony,

Non proprio, ma ho già tonnellate di file allegati ai post in quella directory, non mi dispiace
spostarmi

Risposte:


86

Il solo controllo dell'esistenza del cookie non costituisce una protezione rigorosa.

Per ottenere una protezione più forte, puoi passare o "proxy" tutte le richieste alla cartella caricata (esemplificativa uploadsnel seguente esempio) tramite uno script php:

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

Tutte le richieste di file caricati (che includono immagini nei post) andrebbero a dl-file.phpche quindi può verificare se l'utente ha effettuato l'accesso o meno.

Se l'utente non ha effettuato l'accesso, verrà visualizzato il modulo di accesso ai siti. Dopo che l'utente ha effettuato l'accesso, verrà reindirizzata nuovamente al file e può scaricarlo ora.

Esemplaredl-file.php .

Qualcosa di simile può essere trovato nella \wp-includes\ms-files.phptua installazione di wordpress, ma quello è per il multisito e senza il controllo di accesso e reindirizzamenti.

A seconda di quanto traffico hai, potrebbe essere saggio integrare meglio questo con il tuo server, ad esempio X-Accel-Redirecto le X-Sendfileintestazioni.


1
come si regola dl-file.php se si desidera archiviare i file in una sottodirectory come wp-content / uploads / secure?

Questa è l'unica soluzione davvero sicura. Qualsiasi altra cosa che puoi trovare sul web, come controllare l'intestazione del referer, controllare i cookie, non consentire l'elenco delle directory, è una mezza misura poiché puoi facilmente falsificare le intestazioni delle richieste HTTP per aggirarlo.
Luca,

Ragazzi..questo mi è sembrata la soluzione perfetta .... il problema è che sto usando PDFJS da Mozilla per accedere ad alcuni PDF dalla cartella di upload, e PDFJS usa intestazioni a contenuto parziale per ottenere solo le pagine a cui è interessato. .quindi questa soluzione non è per me. eventuali suggerimenti??
Otto Nascarella,

@OttoNascarella: richieste di contenuti parziali a PHP sono state risolte da oggi, questo è indipendente da questa domanda wordpress. Infatti, la domanda è già piuttosto vecchia: download ripristinabili quando si utilizza PHP per inviare il file?
Hacre,

@hakre Che dire di alcune di quelle immagini utilizzate nella prima pagina del sito Web e di qualsiasi utente che viene a visitare il sito? Mi dà un errore 404 se non ho effettuato l'accesso.
Dhaval Panchal,

14

Puoi anche scrivere un plugin usando l' inithook e il valore get $_GET[ 'file' ];. Se l'utente ha questo valore-get, passa a una funzione per verificare i diritti di accesso ai file: ad esempio con una casella di controllo in una Meta Box.

add_action( 'init', 'fb_init' );
function fb_init() {
    // this in a function for init-hook
    if ( '' != $_GET[ 'file' ] ) {
        fb_get_file( $_GET[ 'file' ] );
    }
}

la funzione 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 not found.' );
    }
    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 ) { // attachment found and parent available
            if ( post_password_required( $image[0] -> post_parent ) ) { // password for the post is not available
                wp_die( get_the_password_form() );// show the password form 
            }
            $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 {
            // not a normal attachment check for thumbnail
            $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' ] ) {// current path of the thumbnail
                            foreach ( $meta[ 'sizes' ] as $SINGLEsize ) {
                                if ( $filename[ 'filename' ] . '.' . $filename[ 'extension' ] == $SINGLEsize[ 'file' ] ) {
                                    if ( post_password_required( $SINGLEimage -> post_parent ) ) { // password for the post is not available
                                        wp_die( get_the_password_form() );// show the password form 
                                    }
                                    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 ); // always send this
    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' );

    // Support for 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'] );
    // If string is empty, return 0. If not, attempt to parse into a timestamp
    $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;

    // Make a timestamp for our most recent modification...
    $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;
    }

    // If we made it this far, just serve the 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;
}

Questo non ha funzionato dalla mia parte qualcuno sa perché? Copio esattamente.
Ryan S,

Protezione funzionante solo pdf. l'estensione di altri file non funziona come: doc, docx, jpg ed ecc ...
Patel,

1

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

  1. Installa il plug-in 'Download Monitor', disponibile su:
    https://wordpress.org/plugins/download-monitor/
  2. Nella dashboard di WordPress, vai alla nuova voce di menu "Download" e aggiungi un nuovo "Download", come descritto sul sito Web della documentazione del plug-in qui: https://www.download-monitor.com/kb/adding-downloads/ . Prendi nota dello shortcode 'Download' fornito per te (es. Salva nel Blocco note). Si noti che il file viene salvato in/wp-content/uploads/dlm_uploads/
  3. Nel metabox "Opzioni di download", specifica "Solo membri" (come documentato qui https://www.download-monitor.com/kb/download-options/ ) e fai clic su "Pubblica".
  4. Nella pagina in cui vuoi che appaia solo il download dei membri, aggiungi lo shortcode di cui hai preso nota al passaggio 2 e "Pubblica / Aggiorna" la pagina, come documentato qui: https://www.download-monitor.com / kb / download di shortcode / . È possibile modificare il modello di collegamento per il download come descritto qui https://www.download-monitor.com/kb/content-templates/ oppure crearne uno proprio (ad es. Per rimuovere il "conteggio" download)
  5. Passa alla tua pagina, dovresti vedere un link per il download (ma che non rivela l'URL al file di download). Se accedi alla stessa pagina in una nuova finestra del browser (o finestra di navigazione in incognito), dovresti scoprire che il download non funziona più.

Ciò significa che chiunque non ha effettuato l'accesso non può né scaricare il file né vedere l'URL reale nel file. Se nel caso in cui qualcuno non autorizzato capisca l'URL del file, il plug-in impedisce anche agli utenti di navigare all'URL del file reale bloccando l'accesso alla /wp-content/uploads/dlm_uploads/cartella.

Bonus: se lo fai per un sito in cui hai bisogno che gli utenti siano in grado di accedere solo come "Membri" (ma non hai autorizzazioni WordPress come la modifica della pagina o come amministratore), installa il plug-in "Membri" https: // wordpress .org / plugins / members / , crea un nuovo ruolo utente chiamato "Membro" e dagli la possibilità unica di "leggere", crea un nuovo utente in WordPress e assicurati di assegnare loro un ruolo di "Membro".

Se si desidera proteggere il contenuto delle pagine, il plug-in "Membri" fornisce alcune opzioni o ci sono altri plugin là fuori. Se vuoi creare un tema della pagina di accesso in modo che i Membri abbiano un aspetto migliore rispetto al modulo di accesso predefinito di WordPress, usa qualcosa come 'Tema il mio accesso': https://wordpress.org/plugins/theme-my-login/


Il processo che ho descritto sopra è anche spiegato qui, anche se come puoi vedere non deve essere specifico per i soli PDF: thedigitalcrowd.com/website-development/wordpress/…
Matty J
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.