Jak chronić przesłane pliki, jeśli użytkownik nie jest zalogowany?


79

Używam wordpress na prywatnej stronie, na której użytkownicy przesyłają pliki. Używam „Prywatnego WordPressa”, aby uniemożliwić dostęp do strony, jeśli użytkownik nie jest zalogowany.

Chciałbym zrobić to samo z plikami przesłanymi w folderze uploads.

Jeśli więc użytkownik nie jest zalogowany, nie będzie mógł uzyskać dostępu do: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf, jeśli spróbuje uzyskać dostęp, ale nie jest zalogowany, powinien zostać przekierowanym na przykład na stronę logowania.

Znalazłem wtyczkę o nazwie prywatne pliki, ale ostatnia aktualizacja została przeprowadzona w 2009 roku i wydaje się, że nie działa na moim wordpress.

Czy ktoś zna jakąś metodę? Czy metoda Hotlinking wystarczy, aby to chronić?

Znalazłem również tę metodę:

# 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

Ale czy jakikolwiek użytkownik, który replikuje plik cookie, może przekazać to prawo? pozdrowienia


1
Czy jest jakiś powód, dla którego nie można użyć innego katalogu przesyłania, takiego jak katalog główny poza witryną?
onetrickpony

Nie bardzo, ale mam już mnóstwo plików dołączonych do postów w tym katalogu, nie mam nic przeciwko przenoszeniu się, jeśli mogę znaleźć właściwe rozwiązanie
chifliiiii

Odpowiedzi:


86

Tylko sprawdzenie, czy plik cookie istnieje, nie stanowi ścisłej ochrony.

Aby uzyskać lepszą ochronę, możesz przekazać lub „proxy” wszystkie żądania do przesłanego folderu (przykład uploadsw poniższym przykładzie) za pomocą skryptu php:

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

Wszystkie prośby o przesłanie plików (które zawierają obrazy w postach) byłyby kierowane do tych, dl-file.phpktóre mogłyby następnie zweryfikować, czy użytkownik jest zalogowany, czy nie.

Jeśli użytkownik nie jest zalogowany, zostanie wyświetlony formularz logowania do witryn. Po zalogowaniu się użytkownik zostanie przekierowany z powrotem do pliku i może go teraz pobrać.

Wzorowedl-file.php .

Coś podobnego można znaleźć w \wp-includes\ms-files.phpinstalacji wordpress, ale ta jest przeznaczona dla wielu witryn i bez sprawdzania logowania i przekierowań.

W zależności od tego, jak dużo ruchu masz, to może być mądry, aby lepiej zintegrować to z Twojego serwera, np X-Accel-Redirectlub X-Sendfilenagłówków.


1
jak dostosować dl-file.php, jeśli chcę przechowywać pliki w podkatalogu, takim jak wp-content / uploads / secure?

To jedyne naprawdę bezpieczne rozwiązanie. Wszystko inne, co można znaleźć w Internecie, takie jak sprawdzanie nagłówka strony odsyłającej, sprawdzanie plików cookie, nie zezwalanie na katalogowanie, jest pół miarą, ponieważ można łatwo sfałszować nagłówki żądań HTTP, aby je obejść.
Łukasz

Chłopaki ... wydawało mi się to idealnym rozwiązaniem dla mnie .... problem polega na tym, że korzystam z PDFJS z Mozilli, aby uzyskać dostęp do niektórych plików PDF z folderu przesyłania, a PDFJS używa nagłówków częściowej zawartości, aby uzyskać tylko te strony, które są zainteresowane. . więc to rozwiązanie jest dla mnie nie do przyjęcia. jakieś sugestie??
Otto Nascarella

@OttoNascarella: Żądania częściowej treści do PHP zostały rozwiązane na dzień dzisiejszy, jest to niezależne od tego pytania wordpress. Rzeczywiście, pytanie jest już dość stare: wznawianie pobierania przy użyciu PHP do wysyłania pliku?
hakre

@hakre Co z niektórymi obrazami użytymi na pierwszej stronie witryny i dowolnym użytkownikiem odwiedzającym witrynę? Daje mi błąd 404, jeśli nie jestem zalogowany.
Dhaval Panchal

14

Możesz także napisać wtyczkę używając inithooka i get-value $_GET[ 'file' ];. Jeśli użytkownik ma tę wartość „get”, wskocz do funkcji, aby sprawdzić prawa dostępu do plików: Na przykład z polem wyboru w polu 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' ] );
    }
}

funkcja 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();
}

Możesz także dodać niestandardowy adres URL plików za pomocą haka 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;
}

To nie działało po mojej stronie, ktoś wie dlaczego? Dokładnie kopiuję.
Ryan S

Ochrona działa tylko pdf. inne rozszerzenie plików nie działa jak: doc, docx, jpg itp.
Patel

1

Jeśli chcesz zastosować podejście oparte na wtyczkach do rozwiązania tego problemu, oto dość dobre rozwiązanie, które (w końcu) znalazłem:

  1. Zainstaluj wtyczkę „Download Monitor”, dostępną pod adresem :
    https://wordpress.org/plugins/download-monitor/
  2. Na pulpicie nawigacyjnym WordPress przejdź do nowej pozycji menu „Pobieranie” i dodaj nowe „Pobieranie”, zgodnie z opisem na stronie z dokumentacją wtyczek: https://www.download-monitor.com/kb/adding-downloads/ . Zwróć uwagę na udostępniony Ci krótki kod „Pobierz” (np. Zapisz w Notatniku). Pamiętaj, że plik zostanie zapisany w/wp-content/uploads/dlm_uploads/
  3. W metaboksie „Opcje pobierania” określ „Tylko członkowie” (zgodnie z dokumentacją tutaj https://www.download-monitor.com/kb/download-options/ ) i kliknij „Publikuj”.
  4. Na stronie, którą członkowie mają tylko pobierać, dodaj krótki kod, który zanotowałeś w kroku 2, i „Opublikuj / zaktualizuj” stronę, jak to udokumentowano tutaj: https://www.download-monitor.com / kb / shortcode-download / . Możesz zmienić szablon łącza do pobierania, jak opisano tutaj https://www.download-monitor.com/kb/content-templates/ , lub utwórz własny (np. W celu usunięcia „licznika” pobierania)
  5. Przejdź do swojej strony, powinieneś zobaczyć link do pobrania (ale który nie ujawnia adresu URL pliku do pobrania). Jeśli przejdziesz do tej samej strony w nowym oknie przeglądarki (lub oknie Incognito), przekonasz się, że pobieranie nie działa.

Oznacza to, że nikt niezalogowany nie może pobrać pliku ani zobaczyć rzeczywistego adresu URL pliku. Jeśli w przypadku, gdy ktoś nieautoryzowany obliczy adres URL pliku, wtyczka przerwie także przeglądanie adresu URL rzeczywistego pliku przez zablokowanie dostępu do /wp-content/uploads/dlm_uploads/folderu.

Bonus: jeśli robisz to dla witryny, w której potrzebujesz, aby użytkownicy mogli logować się tylko jako „Członkowie” (ale nie mają uprawnień WordPress, takich jak edycja strony lub bycie administratorem), zainstaluj wtyczkę „Członkowie” https: // wordpress .org / plugins / Members / , utwórz nową rolę użytkownika o nazwie „Członek” i nadaj jej pojedynczą funkcję „odczytu”, utwórz nowego Użytkownika w WordPress i upewnij się, że nadasz im rolę „Członek”.

Jeśli chcesz chronić zawartość stron, wtyczka „Members” zapewnia pewne opcje lub istnieją inne wtyczki. Jeśli chcesz utworzyć motyw strony logowania, aby członkowie wyglądali lepiej niż domyślny formularz logowania WordPress, użyj czegoś takiego jak „Theme My Login”: https://wordpress.org/plugins/theme-my-login/


Proces, który opisałem powyżej, również został tutaj wyjaśniony, chociaż jak widać, nie musi on być specyficzny tylko dla plików PDF: thedigitalcrowd.com/website-development/wordpress/...
Matty J
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.