web-dev-qa-db-fra.com

Comment limiter le téléchargement de pièces jointes à un utilisateur spécifique?

J'ai un cas d'utilisation très spécifique où le site créé pour un avocat et chacun de ses clients peuvent se connecter à leur propre "page/portail spécifique" (type de message personnalisé) sans possibilité d'accéder à wp-admin, etc. (j'ai créé tous les connexion/enregistrement/pages de modification de profil au début). Dans cette page/portail, l'avocat laissera des messages et des fichiers au client à télécharger , désormais, en théorie, un client peut deviner (ou s'il a connaissance des fichiers d'un autre client) d'autres noms de fichiers et télécharger, créant ainsi un problème. avec confidentialité/sécurité/matériel confidentiel, etc.

Je recherchais des idées/concepts pour une solution, ma pensée initiale était de faire en sorte que le lien de téléchargement pointe vers un fichier download.php qui envoie l'identifiant de la pièce jointe, l'identifiant de l'utilisateur, l'identifiant de la page/du portail et nonce, ainsi que le traitement final. .

qu'est-ce que tu penses? suis-je sur la bonne voie ou cette approche est-elle défectueuse?

Merci!

12
Amit

Ce qu'il faut, c'est que vous ayez besoin de soumettre par proxy des demandes de téléchargement pour les types de fichiers souhaités via WordPress. Supposons que vous allez restreindre l'accès aux fichiers ".doc".

1. Définissez une variable de requête qui indique le fichier demandé

function add_get_file_query_var( $vars ) {
    $vars[] = 'get_file';
    return $vars;
}
add_filter( 'query_vars', 'add_get_file_query_var' );

2. Mettre à jour .htaccess pour transférer les demandes de fichiers restreints vers WordPress

Cela capturera les demandes relatives aux fichiers que vous souhaitez limiter et les renverra à WordPress à l'aide de la variable de requête personnalisée ci-dessus. Insérez la règle suivante avant les lignes RewriteCond.

RewriteRule ^wp-content/uploads/(.*\.docx)$ /index.php?get_file=$1

3. Capturez le nom de fichier demandé dans la variable de requête personnalisée. et vérifiez l'accès au fichier:

function intercept_file_request( $wp ) {
    if( !isset( $wp->query_vars['get_file'] ) )
        return;

    global $wpdb, $current_user;

    // Find attachment entry for this file in the database:
    $query = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid='%s'", $_SERVER['REQUEST_URI'] );
    $attachment_id = $wpdb->get_var( $query );

    // No attachment found. 404 error.  
    if( !$attachment_id ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Get post from database 
    $file_post = get_post( $attachment_id );
    $file_path = get_attached_file( $attachment_id );

    if( !$file_post || !$file_path || !file_exists( $file_path ) ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Logic for validating current user's access to this file...
    // Option A: check for user capability
    if( !current_user_can( 'required_capability' ) ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Option B: check against current user
    if( $current_user->user_login == "authorized_user" ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Everything checks out, user can see this file. Simulate headers and go:
    header( 'Content-Type: ' . $file_post->post_mime_type );
    header( 'Content-Dispositon: attachment; filename="'. basename( $file_path ) .'"' );
    header( 'Content-Length: ' . filesize( $file_path ) );

    echo file_get_contents( $file_path );
    die(0);
}
add_action( 'wp', 'intercept_file_request' );

NBCette solution fonctionne pour des installations sur site unique uniquement ! En effet, WordPress MU transfère déjà les demandes de fichiers téléchargés dans les sous-sites via wp-includes/ms-files.php. Il existe également une solution pour WordPress MU, mais elle est un peu plus complexe.

5
Bendoh

J'ai récemment eu un problème connexe et j'ai écrit cet article à ce sujet .

Je présume que les téléchargements sont téléchargés via la gestion des supports de WordPress - ou sinon, vous avez un ID de pièce jointe pour le téléchargement.

Esquisse de solution

  • Sécurisez le répertoire de téléchargement (en ce sens, je _ {seulement veux dire utiliser .htaccess pour bloquer toute tentative d'accès direct aux fichiers du répertoire de téléchargement (ou de l'un de leurs sous-répertoires) - par exemple via mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)
  • Créez un lien de téléchargement comprenant l'ID de la pièce jointe - cela passe par WordPress pour vérifier si l'utilisateur a le droit de voir la pièce jointe autorise/refuse l'accès.

Mises en garde

  • Ceci utilise .htaccess pour assurer la sécurité . Si ceci n'est pas disponible/activé (serveurs nginx par exemple), vous n'aurez pas beaucoup de sécurité. Vous pouvez empêcher l'utilisateur navigation le répertoire uplods. Mais l'accès direct fonctionnera.
  • Comme ci-dessus. Cela ne devrait pas être utilisé dans la distribution si vous avez besoin d'une sécurité absolue . C'est bien si votre configuration spécifique fonctionne - mais en général, cela ne peut pas être garanti. Mon article lié tente en partie de résoudre ce problème.
  • Vous perdrez des vignettes . Si vous bloquez l’accès direct à un dossier ou à un sous-dossier, les miniatures des fichiers de ce dossier ne pourront plus être visualisées. Mon article lié tente en partie de résoudre ce problème.

Blocage de l'accès direct

Pour ce faire, dans votre dossier de téléchargements (ou dans un sous-dossier - tous les documents confidentiels doivent résider, quelle que soit leur profondeur, dans ce dossier). Placez un fichier .htaccess avec les éléments suivants:

Order Deny,Allow
Deny from all

Dans ce qui suit, je suppose que vous joindrez des informations confidentielles au type de message 'client'. Tout support téléchargé sur la page de modification du client sera stocké dans le dossier uploads/conf/

La fonction pour configurer le répertoire des téléchargements protégés

function wpse26342_setup_uploads_dir(){

    $wp_upload_dir = wp_upload_dir();
    $protected_folder = trailingslashit($wp_upload_dir['basedir']) . 'conf';    

    // Do not allow direct access to files in protected folder
    // Add rules to /uploads/conf/.htacess
    $rules = "Order Deny,Allow\n";
    $rules .= "Deny from all";

    if( ! @file_get_contents( trailingslashit($protected_folder).'.htaccess' ) ) {
            //Protected directory doesn't exist - create it.
        wp_mkdir_p( $protected_folder);
    }
    @file_put_contents( trailingslashit($protected_folder).'.htaccess', $rules );

     //Optional add blank index.php file to each sub-folder of protected folder.
}

Téléchargement de matériel confidentiel

   /**
    * Checks if content is being uploaded on the client edit-page
    * Calls a function to ensure the protected file has the .htaccess rules
    * Filters the upload destination to the protected file
    */
    add_action('admin_init', 'wpse26342_maybe_change_uploads_dir', 999);
    function wpse26342_maybe_change_uploads_dir() {
        global $pagenow;

        if ( ! empty( $_POST['post_id'] ) && ( 'async-upload.php' == $pagenow || 'media-upload.php' == $pagenow ) ) {
                if ( 'client' == get_post_type( $_REQUEST['post_id'] ) ) {
                       //Uploading content on the edit-client page

                       //Make sure uploads directory is protected
                       wpse26342_setup_uploads_dir();

                       //Change the destination of the uploaded file to protected directory.
                       add_filter( 'upload_dir', 'wpse26342_set_uploads_dir' );
                }
        }

    }

Cela fait, le contenu téléchargé devrait se trouver dans uploads/conf et essayer d'y accéder directement à l'aide de votre navigateur ne fonctionnerait pas.

Télécharger du contenu

C'est facile. L'URL de téléchargement peut être quelque chose www.site.com?wpse26342download=5 (où 5 est l'ID de pièce jointe du contenu téléchargé). Nous l'utilisons pour identifier la pièce jointe, vérifier les autorisations de l'utilisateur actuel et lui permettre de télécharger.

Tout d'abord, configurez la variable de requête

/**
 * Adds wpse26342download to the public query variables
 * This is used for the public download url
 */
add_action('query_vars','wpse26342_add_download_qv');
function wpse26342_add_download_qv( $qv ){
    $qv[] = 'wpse26342download';
    return $qv;
}}

Maintenant, configurez un auditeur pour (peut-être) déclencher le téléchargement ...

add_action('request','wpse26342_trigger_download');
function wpse26342_trigger_download( $query_vars ){

        //Only continue if the query variable set and user is logged in...
    if( !empty($query_vars['wpse26342download']) && is_user_logged_in() ){

        //Get attachment download path
        $attachment = (int) $query_vars['wpse26342download'];
        $file = get_attached_file($attachment);

        if( !$file )
             return;

        //Check if user has permission to download. If not abort.       
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));

        ob_clean();
        flush();
        readfile($file);
        exit();
    }
    return $query_vars;
}

Commentaires finaux

Le code ci-dessus peut contenir des erreurs de syntaxe/bugs et n'a pas été testé. Vous l'utilisez à vos risques et périls :).

L'URL de téléchargement peut être "raffinée" à l'aide de réécritures. Comme indiqué dans les commentaires, vous pouvez ajouter un index.php vierge à l'intérieur de chaque enfant du dossier protégé afin d'empêcher toute navigation. Toutefois, les règles .htaccess devraient néanmoins empêcher ce type de navigation.

Une méthode plus sécurisée consisterait à stocker les fichiers publics en dehors d'un répertoire public. Ou sur un service externe comme Amazon S3. Pour ce dernier, vous devrez générer une URL valide pour extraire le fichier d'Amazon (à l'aide de votre clé privée). Les deux nécessitent un certain niveau de confiance dans votre service hôte/tiers.

Je me méfierais de l'utilisation de plug-ins suggérant qu'ils offrent des "téléchargements protégés". Je n'en ai trouvé aucun qui offre une sécurité suffisante. Ne faites pas non plus les mises en garde de cette solution - et toute suggestion ou critique sera la bienvenue.

3
Stephen Harris

Vous connaissez probablement cette astuce. Ce code vérifie le nom d'utilisateur de l'utilisateur actuellement connecté et, s'il correspond, affiche le lien de téléchargement correspondant à ce fichier, sinon rien ne s'affichera.

voici le code:

<?php 
    global $current_user;
    get_currentuserinfo();

    if ( 'username' == $current_user->user_login ) {
        echo 'Download Link';
    } else {
        // nothing
    }
?>

Cependant, cela ne sera pas une bonne approche, car les fichiers sont stockés sur des serveurs, toute personne disposant d'un lien peut télécharger ce fichier.

1
amit

Je pense que le cryptage des fichiers est la voie à suivre comme la réponse ci-dessus. Il existe un plugin sur Wordpress.org qui vous permet de protéger les téléchargements. http://wordpress.org/extend/plugins/download-protect/ Vous pouvez également utiliser le service amazon ou google drive. Il existe de nombreux services proposant des téléchargements protégés tels que les boîtes de dépôt.

0
Chris

Je présume que ces informations sont confidentielles et qu’en plus de masquer les liens vers les fichiers, vous souhaitez les rendre totalement inaccessibles à quiconque sur le Web, même s’ils devaient deviner l’URL, à moins que cet utilisateur ne dispose de la permission explicite de télécharger. les fichiers.

Recherchez dans le stockage des fichiers sur Amazon S3 de manière sécurisée, puis indiquez les URL pré-signées (limitées dans le temps) du fichier, à condition que les contrôles de sécurité appropriés aient été satisfaits (l'utilisateur s'est connecté à votre compte). site et qui ils disent être).

Il existe un très bon AWS SDK qui permet de le faire très simplement.

Ce que vous devez rechercher, c'est comment envoyer des fichiers téléchargés via l'interface de téléchargement WP vers S3. Vous pouvez également créer votre propre uploader .

Une autre option serait aussi de regarder dans le code de WP e-commerce . Ils offrent un téléchargement sécurisé des fichiers logiciels (par exemple, MP3). Je crois que les fichiers sont convertis en hachages avec une clé de chiffrement générée par utilisateur lors de l'achat. Cela prendrait un peu de déchiffrement pour voir comment cela fonctionnait, mais le processus n'étant pas unique à ce plugin, d'autres exemples seront disponibles (quelque part).

0
deadlyhifi