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

80

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.

Donc, si un utilisateur n’est pas connecté, il ne pourra pas accéder à: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf s’ils essaient d’y accéder mais qu’ils ne sont pas connectés, ils doivent le faire. être redirigé 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

chifliiiii
la source
1
Une raison pour laquelle vous ne pouvez pas utiliser un répertoire de téléchargement différent, comme celui situé en dehors de la racine du site?
Onetrickpony
Pas vraiment, mais j'ai déjà des tonnes de fichiers attachés à des publications dans ce répertoire, cela ne me dérange pas de me déplacer si je peux trouver une solution appropriée
chifliiiii

Réponses:

86

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

Pour obtenir une protection renforcée, vous pouvez transmettre ou "proxy" toutes les demandes au dossier téléchargé (à titre d'exemple uploadsdans 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 messages) iraient à dl-file.phpce qui peut ensuite 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.

Exemplairedl-file.php .

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

En fonction de votre trafic, il pourrait être judicieux de mieux l'intégrer à votre serveur, par exemple, à des en X-Accel-Redirect- X-Sendfiletêtes.

hakre
la source
1
comment ajustez-vous dl-file.php si je veux stocker les fichiers dans un sous-répertoire tel que wp-content / uploads / secure?
C'est la seule solution vraiment sécurisée. Tout ce que vous pouvez trouver sur le Web, comme la vérification de l'en-tête du référent, la vérification des cookies, l'annulation de la liste des répertoires, est une demi-mesure, car vous pouvez facilement usurper les en-têtes des demandes HTTP pour le contourner.
Luc
Les gars..cela semblait être la solution parfaite pour moi ... le problème est que j'utilise PDFJS de Mozilla pour accéder à certains PDF à partir du dossier de téléchargement, et PDFJS utilise des en-têtes de contenu partiel pour obtenir uniquement les pages qui l'intéressent .. .so cette solution est un non-partant pour moi. Aucune suggestion??
Otto Nascarella
@OttoNascarella: Les demandes de contenu partielles adressées à PHP ont été résolues à ce jour, ceci est indépendant de cette question wordpress. Enfait, la question est déjà assez ancienne: téléchargements résumables lors de l'utilisation de PHP pour envoyer le fichier?
hakre
@hakre Qu'en est-il de certaines des images utilisées en première page du site Web et des utilisateurs qui viennent visiter le site? Cela me donne une erreur 404 si je ne suis pas connecté.
Dhaval Panchal
14

Vous pouvez également écrire un plugin en utilisant le inithook et la 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;
}
bueltge
la source
Cela n'a pas fonctionné de mon côté, quelqu'un sait pourquoi? Je copie exactement.
Ryan S
Protection fonctionnant uniquement en pdf. Les autres extensions de fichiers ne fonctionnent pas comme: doc, docx, jpg, etc.
Patel
1

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 à l' adresse suivante :
    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", indiquez "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 le vôtre (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 du 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 /wp-content/uploads/dlm_uploads/dossier.

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", attribuez-lui la seule capacité de "lecture", créez un nouvel utilisateur dans WordPress et assurez-vous de leur attribuer le 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 quelque chose comme "Thème Mon login": https://wordpress.org/plugins/theme-my-login/

Matty J
la source
Le processus que j'ai décrit ci-dessus est également expliqué ici, bien que, comme vous pouvez le constater, il ne doit pas nécessairement être spécifique aux PDF: thedigitalcrowd.com/website-development/wordpress/…
Matty J