Як обмежити завантаження вкладень певному користувачеві?


12

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

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

що ти думаєш? я на правильному шляху чи такий підхід хибний?

Дякую!


Ви знайшли рішення для цього?
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, але це трохи більше.


1
Привіт, я не бачу, що ви підключаєте цю функцію поетапно intercept_file_requestабо її викликають куди завгодно, як ця функція звільняється?
Бобз

Хороший момент, це слід підключити wp, я оновив приклад.
Бендо

3

Нещодавно у мене була пов'язана проблема, і я написав про це цю статтю .

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

Структура рішення

  • Зробіть каталог завантажень "захищеним" (У цьому сенсі я просто маю на увазі використання .htaccessдля блокування будь-якої спроби прямого доступу до файлів у каталозі завантажень (або в його підкаталозі) - наприклад, через mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)
  • Створіть посилання для завантаження, включаючи ідентифікатор вкладеного файлу - це проходить через WordPress, щоб перевірити дозвіл користувача на перегляд вкладення, що дозволяє / забороняє доступ.

Коваджі

  • Це використовує .htaccessдля забезпечення безпеки . Якщо це недоступно / увімкнено (наприклад, nginx-сервери), ви не отримаєте великої безпеки. Ви можете запобігти перегляду користувачем каталогу оновлень. Але прямий доступ спрацює.
  • Як зазначено вище. Це не повинно використовуватися для розповсюдження, якщо вам потрібна абсолютна безпека . Це добре, якщо ваша конкретна установка працює - але в цілому, це не може бути гарантовано. Моя пов'язана стаття частково намагається вирішити це питання.
  • Ви втратите мініатюри . Блокування прямого доступу до папки або підпапки означатиме, що ескізи файлів у цій папці неможливо переглянути. Моя пов'язана стаття частково намагається вирішити це питання.

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

Для цього в папці завантаження (або в підпапці - весь конфіденційний матеріал повинен знаходитися на будь-якій глибині всередині цієї папки). Помістіть .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). Я вважаю, що файли перетворюються в хеші з ключем шифрування, який генерується на кожного користувача при покупці. Це потребує дешифрування, щоб побачити, як він працює, але цей процес не буде унікальним для цього плагіна, тому інші приклади (десь) будуть доступні.


0

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


безпека через невідомість - це поганий підхід. будь-хто зможе побачити http-запит і отримати URL-адресу таким чином.
mulllhausen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.