web-dev-qa-db-fra.com

Comment protéger les téléchargements, si l'utilisateur n'est pas connecté?

J'utilise wordpress pour un site privé où les utilisateurs téléchargent des fichiers. J'utilise le "WordPress privé" pour empêcher l'accès au site si l'utilisateur n'est pas connecté.

Je voudrais faire la même chose pour les fichiers téléchargés dans le dossier uploads.

Ainsi, si un utilisateur n'est pas connecté, il ne pourra pas accéder à: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf s'il tente d'y accéder mais qu'il ne le fait pas. connecté, ils doivent être redirigés vers la page de connexion par exemple.

J'ai trouvé un plugin appelé fichiers privés, mais la dernière fois mis à jour était en 2009 et il ne semble pas fonctionner sur mon wordpress.

Quelqu'un connaît une méthode? La méthode Hotlinking suffira-t-elle à protéger cela?

J'ai aussi trouvé cette méthode:

# 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

Mais alors tout utilisateur qui réplique le cookie peut-il passer ce droit? Cordialement

77
chifliiiii

Vérifier que le cookie existe n'est pas une protection stricte.

Pour obtenir une protection renforcée, vous pouvez transmettre ou "utiliser un proxy" à toutes les demandes du dossier téléchargé (exemple uploads dans l'exemple suivant) via un script php:

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

Toutes les demandes de fichiers téléchargés (y compris les images dans les publications) iraient à dl-file.php, ce qui permet ensuite de vérifier si l'utilisateur est connecté ou non.

Si l'utilisateur n'est pas connecté, le formulaire de connexion de votre site sera affiché. Une fois l’utilisateur connecté, il sera redirigé vers le fichier et pourra le télécharger maintenant.

Exemple dl-file.php .

Quelque chose de similaire peut être trouvé dans \wp-includes\ms-files.php dans votre installation de wordpress, mais celui-ci est pour multisite et sans contrôle de connexion et redirections.

En fonction de votre trafic, il peut être judicieux de mieux l'intégrer à votre serveur, par exemple. X-Accel-Redirect ou X-Sendfile en-têtes.

82
hakre

Vous pouvez également écrire un plugin en utilisant le hook init et le get-value $_GET[ 'file' ];. Si l'utilisateur a cette valeur d'obtention, sautez dans une fonction pour vérifier les droits d'accès aux fichiers: Par exemple, avec une case à cocher dans une 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 fonction 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();
}

Vous pouvez également ajouter une URL personnalisée pour les fichiers via le 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;
}
14
bueltge

Si vous souhaitez une approche basée sur un plugin pour résoudre ce problème, voici une solution relativement bonne que j'ai (enfin) trouvée:

  1. Installez le plugin 'Download Monitor', disponible sur:
    https://wordpress.org/plugins/download-monitor/
  2. Dans le tableau de bord WordPress, accédez au nouvel élément de menu "Téléchargements" et ajoutez un nouveau "Télécharger", comme décrit sur le site Web de la documentation du plugin ici: https://www.download-monitor.com/kb/adding-downloads/ . Prenez note du shortcode "Télécharger" fourni (par exemple, enregistrer dans le Bloc-notes). Notez que le fichier est enregistré dans /wp-content/uploads/dlm_uploads/
  3. Dans la boîte à outils "Options de téléchargement", spécifiez "Membres uniquement" (comme documenté ici https://www.download-monitor.com/kb/download-options/ ), puis cliquez sur "Publier".
  4. Sur la page à télécharger uniquement par les membres, ajoutez le shortcode dont vous avez pris note à l'étape 2 et "Publiez/Mettez à jour" la page, comme indiqué ici: https: //www.download-monitor .com/kb/shortcode-download/ . Vous pouvez modifier le modèle de lien de téléchargement comme décrit ici https://www.download- Monitor.com/kb/content-templates/ , ou créer votre propre modèle (par exemple, pour supprimer le nombre de téléchargements).
  5. Accédez à votre page, vous devriez voir un lien de téléchargement (mais qui ne révèle pas l’URL du fichier téléchargé). Si vous accédez à la même page dans une nouvelle fenêtre de navigateur (ou une fenêtre de navigation privée), vous devriez constater que le téléchargement ne fonctionne plus.

Cela signifie que les personnes non connectées ne peuvent ni télécharger le fichier, ni voir l'URL réelle du fichier. Si, au cas où une personne non autorisée déterminerait l'URL du fichier, le plug-in empêche également les utilisateurs d'accéder à l'URL du fichier réel en bloquant l'accès au dossier /wp-content/uploads/dlm_uploads/.

Bonus: si vous faites cela pour un site où vous avez besoin que les utilisateurs puissent se connecter en tant que 'Membres' (sans aucune autorisation WordPress comme l'édition de page ou en tant qu'administrateur), installez le plugin 'Membres' https://wordpress.org/plugins/members/ , créez un nouveau rôle d'utilisateur appelé 'Membre' et donnez-lui la capacité unique de 'lire', créez un nouvel utilisateur dans WordPress et assurez-vous de lui attribuer un rôle de ' Membre'.

Si vous souhaitez protéger le contenu des pages, le plug-in "Membres" fournit certaines options ou d'autres plug-ins. Si vous souhaitez personnaliser la page de connexion pour que les membres aient une meilleure apparence que le formulaire de connexion par défaut WordPress, utilisez le mot-clé 'Theme My Login': https://wordpress.org/plugins/theme-my-login/

1
Matty J