Как ограничить загрузку вложений конкретным пользователем?

12

У меня есть очень специфический случай использования, когда сайт создан для адвоката, и каждый из его клиентов может войти на свою собственную «определенную страницу / портал» (пользовательский тип сообщения) без возможности доступа к wp-admin и т. Д. (Я создал все страницы входа / регистрации / редактирования профиля в интерфейсе). На этой странице / портале юрист оставит сообщения и файлы для загрузки клиентом , теперь, теоретически, один клиент может угадать (или, если знает о файлах другого клиента) другие имена файлов и загрузить их, создавая таким образом проблему с конфиденциальностью / безопасностью. / конфиденциальный материал и т. д.

Я ищу идеи / концепции для решения, моей первоначальной мыслью было, чтобы ссылка на скачивание указывала на какой-то файл download.php, отправляющий идентификатор вложения, идентификатор пользователя, идентификатор страницы / портала и одноразовый номер, а затем обрабатывал их на другом конце. ,

что вы думаете? я на правильном пути или этот подход имеет недостатки?

Благодарность!

Amit
источник
Вы нашли решение для этого?
brasofilo
@brasofilo, нет ..
Амит

Ответы:

6

Что должно произойти, это то, что вам нужно прокси-запросы на загрузку для типов файлов, которые вы хотите через WordPress. Предположим, вы собираетесь ограничить доступ к файлам ".doc".

1. Определите переменную запроса, которая указывает запрошенный файл

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

2. Обновите .htaccess для пересылки запросов на запрещенные файлы в WordPress

Это будет захватывать запросы к файлам, которые вы хотите ограничить, и отправлять их обратно в WordPress, используя указанную выше переменную запроса. Вставьте следующее правило перед RewriteCondстроками.

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

3. Захват запрошенного имени файла в пользовательскую переменную запроса; и проверьте доступ к файлу:

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' );

NB Это решение работает для одноузельных устанавливается только ! Это связано с тем, что WordPress MU уже перенаправляет запросы загруженных файлов на дочерние сайты wp-includes/ms-files.php. Существует также решение для WordPress MU, но оно немного сложнее.

Bendoh
источник
1
Привет, я не вижу, что вы перехватываете эту функцию на шаге intercept_file_requestили она вызывается в любом месте, как эта функция запускается?
Бобз
Хороший вопрос, это надо зацепить wp, я обновил пример.
Бендо
3

У меня недавно была связанная проблема, и я написал эту статью об этом .

Я предполагаю, что загружаемые файлы загружаются с помощью медиа-обработки WordPress, иначе у вас есть идентификатор вложения для загрузки.

План решения

  • Сделать каталог дату загрузки «безопасный» (В этом смысле я просто среднее использование , .htaccessчтобы блокировать любые попытки доступа непосредственно файлы в директории загрузок (или подкаталог таковой) - например , через mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)
  • Создайте ссылку для загрузки, включающую в себя идентификатор вложения - это проходит через WordPress, чтобы проверить разрешение пользователя на просмотр вложения, разрешает / запрещает доступ.

Предостережения

  • Это использует .htaccessдля обеспечения безопасности . Если это недоступно / включено (например, на серверах nginx), вы не получите особой безопасности. Вы можете запретить пользователю просматривать каталог uplods. Но прямой доступ будет работать.
  • Согласно выше. Это не должно использоваться при распространении, если вам требуется абсолютная безопасность . Хорошо, если ваша конкретная настройка работает, но в целом это не может быть гарантировано. Моя связанная статья частично пытается решить эту проблему.
  • Вы потеряете миниатюры . Блокировка прямого доступа к папке или подпапке будет означать, что миниатюры файлов в этой папке не могут быть просмотрены. Моя связанная статья частично пытается решить эту проблему.

Блокировка прямого доступа

Для этого в папке загрузки (или подпапке - весь конфиденциальный материал должен находиться на любой глубине внутри этой папки). Поместите .htaccessфайл со следующим:

Order Deny,Allow
Deny from all

Далее я предполагаю, что вы будете прикреплять конфиденциальный материал к типу записи «клиент». Все медиафайлы, загруженные на страницу редактирования клиента, будут храниться в uploads/conf/папке.

Функция для настройки защищенного каталога загрузок

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.
}

Загрузка конфиденциального материала

   /**
    * 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' );
                }
        }

    }

Сделав это, загруженный контент должен быть внутри, uploads/confи попытка доступа к нему напрямую через браузер не должна работать.

Загрузка контента

Это легко. URL-адрес загрузки может быть чем-то www.site.com?wpse26342download=5(где 5 - идентификатор вложения загруженного контента). Мы используем это, чтобы определить вложение, проверить права доступа текущего пользователя и разрешить его загрузку.

Сначала настройте переменную запроса

/**
 * 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;
}}

Теперь настройте слушателя, чтобы (возможно) вызвать загрузку ...

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;
}

Заключительные комментарии

Приведенный выше код может содержать ошибки / синтаксические ошибки и не проверен, и вы используете его на свой страх и риск :).

URL-адрес загрузки может быть «предварительно подтвержден» с помощью переписывания. Как указано в комментариях, вы можете добавить пробел index.phpвнутри каждого дочернего элемента защищенной папки, чтобы предотвратить просмотр, но в .htaccessлюбом случае это должно быть предотвращено правилами.

Более безопасный способ - хранить публичные файлы вне публичного каталога. Или на внешнем сервисе, таком как Amazon S3. Для последнего вам потребуется сгенерировать действительный URL для получения файла из Amazon (используя ваш закрытый ключ). Оба из них требуют определенного уровня доверия к вашему хосту / стороннему сервису.

Я бы с осторожностью использовал любые плагины, которые предлагают «защищенные загрузки». Я не нашел ни одного, обеспечивающего достаточно хорошую безопасность. Пожалуйста, не будьте осторожны с этим решением - и я буду рад любым предложениям или критике.

Стивен Харрис
источник
1

Возможно, вы знали этот трюк. Этот код проверит текущее имя пользователя, вошедшего в систему, и, если он совпадет, отобразит ссылку на скачивание этого файла, иначе он ничего не отобразит.

вот код:

<?php 
    global $current_user;
    get_currentuserinfo();

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

Однако это не будет хорошим подходом, так как файлы хранятся на серверах, любой, у кого есть ссылка, может скачать этот файл.

Амит
источник
0

Я предполагаю, что эта информация является конфиденциальной, и поэтому помимо скрытия ссылок на файлы, вы захотите сделать их полностью недоступными для любого пользователя в Интернете, даже если он должен был угадать URL, если только у этого пользователя нет явного разрешения на загрузку. файлы.

Рассмотрите возможность безопасного хранения файлов на Amazon S3 и затем предоставьте предварительно подписанные (ограниченные по времени) URL-адреса для файла при условии, что были выполнены правильные проверки безопасности (т. Е. Пользователь вошел на ваш сайт и является тем, кем, по его словам, он является).

Существует очень хороший AWS SDK, который делает это очень просто.

Вам нужно изучить, как вместо этого отправлять файлы, загруженные через интерфейс загрузки WP, в S3, или создать собственный загрузчик .

Другие варианты будут слишком заглядывать в код WP электронной коммерции . Они предлагают безопасную загрузку файлов программного обеспечения (например, MP3). Я считаю, что файлы конвертируются в хэши с ключом шифрования, который генерируется для каждого пользователя при покупке. Это потребует некоторого расшифровки, чтобы увидеть, как это работает, но процесс не будет уникальным для этого плагина, поэтому другие примеры будут доступны (где-то).

deadlyhifi
источник
0

Я думаю, что шифрование файлов - это путь, подобный приведенному выше ответу. На Wordpress.org есть плагин, который позволяет защищать загрузки. http://wordpress.org/extend/plugins/download-protect/ Вы также можете использовать сервис amazons или google drive. Существует множество сервисов, предлагающих защищенные загрузки, такие как Drop Box.

Крис
источник
безопасность через неизвестность - плохой подход. любой сможет увидеть запрос http и получить URL таким образом.
mulllhausen