Как защитить загрузки, если пользователь не вошел в систему?

80

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

Я хотел бы сделать то же самое с файлами, загруженными в папку загрузки.

Поэтому, если пользователь не вошел в систему, он не сможет получить доступ к: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf, если он попытается получить доступ, но не вошел в систему, ему следует например, быть перенаправленным на страницу входа.

Я нашел плагин под названием личные файлы, но последний раз обновлялся в 2009 году, и он, похоже, не работает на моем WordPress.

Кто-нибудь знает какой-нибудь метод? Hotlinking метод будет достаточно, чтобы защитить это?

Я также нашел этот метод:

# 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

Но тогда любой пользователь, который копирует cookie, может передать это право? С уважением

chifliiiii
источник
1
Есть ли причина, по которой вы не можете использовать другой каталог для загрузки, например, вне корня сайта?
onetrickpony
Не совсем, но у меня уже есть тонны файлов, прикрепленных к сообщениям в этом каталоге, я не возражаю передвигаться, если смогу найти правильное решение
chifliiiii

Ответы:

86

Только проверка, существует ли cookie, не является строгой защитой.

Чтобы получить более надежную защиту, вы можете передать или «прокси» все запросы к загруженной папке (пример uploadsв следующем примере) через скрипт php:

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

Все запросы к загруженным файлам (которые включают в себя изображения в сообщениях) будут направлены на то, dl-file.phpчто затем может проверить, вошел ли пользователь в систему или нет.

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

Примерныеdl-file.php .

Нечто подобное можно найти в \wp-includes\ms-files.phpвашей установке WordPress, но это для мультисайта и без проверки входа и перенаправления.

В зависимости от того, сколько трафика у вас есть, это может быть мудрым , чтобы лучше интегрировать это с вашим сервером, например , X-Accel-Redirectили X-Sendfileзаголовков.

hakre
источник
1
Как настроить dl-file.php, если я хочу хранить файлы в подкаталоге, например, wp-content / uploads / secure?
Это единственное действительно безопасное решение. Все остальное, что вы можете найти в Интернете, например, проверка заголовка реферера, проверка файлов cookie, запрет списка каталогов, является полумерой, поскольку вы можете легко подделать заголовки HTTP-запросов, чтобы обойти это.
Люк
Ребята ... мне показалось, что это идеальное решение ... проблема в том, что я использую PDFJS от Mozilla для доступа к некоторым PDF-файлам из папки загрузки, а PDFJS использует частичные заголовки контента, чтобы получить только те страницы, которые ему интересны .. . так что это решение не подходит для меня. какие-либо предложения??
Отто Наскарелла
@ OttoNascarella: Частичные запросы контента в PHP были решены на сегодняшний день, это не зависит от этого вопроса WordPress. Infact, вопрос уже довольно старый: возобновляемые загрузки при использовании PHP для отправки файла?
hakre
@hakre Как насчет некоторых из этих изображений, используемых на главной странице сайта, и любой пользователь посещает сайт? Это дает мне ошибку 404, если я не вошел в систему.
Давал Панчал
14

Вы также можете написать плагин, используя inithook и get-value $_GET[ 'file' ];. Если у пользователя есть это get-значение, перейдите в функцию для проверки прав доступа к файлам: например, с помощью флажка в 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' ] );
    }
}

функция 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();
}

Вы также можете добавить пользовательский URL для файлов через хук 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
источник
Это не работает на моей стороне, кто-нибудь знает почему? Я точно копирую.
Райан С
Защита работает только pdf. Расширение других файлов не работает, как: DOC, DOCX, JPG и т. д.
Patel
1

Если вам нужен подход на основе плагинов для решения этой проблемы, вот довольно хорошее решение, которое я (наконец) нашел:

  1. Установите плагин «Download Monitor», доступный по адресу:
    https://wordpress.org/plugins/download-monitor/
  2. В панели управления WordPress перейдите в новый пункт меню «Загрузки» и добавьте новую «Загрузку», как описано на веб-сайте документации плагина: https://www.download-monitor.com/kb/adding-downloads/ . Запомните предоставленный вам шорткод «Скачать» (например, сохранить в блокноте). Обратите внимание, что файл сохраняется в/wp-content/uploads/dlm_uploads/
  3. В метабоксе «Параметры загрузки» укажите «Только участники» (как описано здесь https://www.download-monitor.com/kb/download-options/ ) и нажмите «Опубликовать».
  4. На странице, которую вы хотите, чтобы отображались только загружаемые пользователи, добавьте шорткод, который вы отметили на шаге 2, и «Публикация / обновление» на странице, как описано здесь: https://www.download-monitor.com / kb / shortcode-download / . Вы можете изменить шаблон ссылки на скачивание, как описано здесь https://www.download-monitor.com/kb/content-templates/ , или создать свой собственный (например, чтобы удалить количество загрузок)
  5. Перейдите на свою страницу, вы должны увидеть ссылку на скачивание (но там не указан URL к файлу загрузки). Если вы перейдете на ту же страницу в новом окне браузера (или в окне Incognito), вы обнаружите, что загрузка больше не работает.

Это означает, что любой, кто не вошел в систему, не может ни загрузить файл, ни увидеть реальный URL-адрес файла. Если в случае, если кто-то неавторизованный выяснит URL-адрес файла, плагин также останавливает пользователей, просматривающих реальный URL-адрес файла, блокируя доступ к /wp-content/uploads/dlm_uploads/папке.

Бонус: если вы делаете это для сайта, где вам нужно, чтобы пользователи могли входить в систему только как «участники» (но не имеют прав WordPress, таких как редактирование страниц или администратор), установите плагин «участники» https: // wordpress .org / plugins / members / , создайте новую роль пользователя с именем «Member» и предоставьте ей единственную возможность «чтения», создайте нового пользователя в WordPress и убедитесь, что ему назначена роль «Member».

Если вы хотите защитить содержимое страниц, плагин «Участники» предоставляет некоторые опции или есть другие плагины. Если вы хотите, чтобы страница входа для участников отображалась лучше, чем форма входа в WordPress по умолчанию, используйте что-то вроде «Тема моего входа»: https://wordpress.org/plugins/theme-my-login/

Мэтти Дж
источник
Процесс, который я описал выше, также объясняется здесь, хотя, как вы можете видеть, он не должен быть специфичным только для PDF-файлов: thedigitalcrowd.com/website-development/wordpress/…
Matty J