Wie werden Uploads geschützt, wenn der Benutzer nicht angemeldet ist?

79

Ich benutze WordPress für eine private Site, auf der Benutzer Dateien hochladen. Ich verwende "Private WordPress", um den Zugriff auf die Site zu verhindern, wenn der Benutzer nicht angemeldet ist.

Ich möchte dasselbe mit den Dateien machen, die im Upload-Ordner hochgeladen wurden.

Wenn ein Benutzer also nicht angemeldet ist, kann er nicht auf Folgendes zugreifen: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf. Wenn er versucht, darauf zuzugreifen, aber nicht angemeldet ist, sollte er dies tun Sie werden beispielsweise zur Anmeldeseite weitergeleitet.

Ich habe ein Plugin namens private files gefunden, aber das letzte Update war 2009 und es scheint nicht auf meinem WordPress zu funktionieren.

Kennt jemand eine Methode? Hotlinking-Methode wird ausreichen, um dies zu schützen?

Ich habe auch diese Methode gefunden:

# 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

Aber dann könnte jeder Benutzer, der das Cookie repliziert, dieses Recht bestehen? Grüße

chifliiiii
quelle
1
Gibt es einen Grund, warum Sie kein anderes Upload-Verzeichnis als das außerhalb des Site-Stammverzeichnisses verwenden können?
onetrickpony
Nicht wirklich, aber ich habe bereits Unmengen von Dateien an Beiträge in diesem Verzeichnis angehängt. Es macht mir
nichts aus, mich umzusehen,

Antworten:

86

Nur zu prüfen, ob das Cookie existiert, ist kein strenger Schutz.

Um einen stärkeren Schutz zu erhalten, können Sie alle Anforderungen an den hochgeladenen Ordner ( uploadsim folgenden Beispiel beispielhaft) über ein PHP-Skript übergeben oder "vertreten" :

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

Alle Anfragen an hochgeladene Dateien (die Bilder in Posts enthalten) gehen an dl-file.phpdie dann überprüfen kann, ob der Benutzer angemeldet ist oder nicht.

Wenn der Benutzer nicht angemeldet ist, wird das Anmeldeformular Ihrer Site angezeigt. Nachdem sich der Benutzer angemeldet hat, wird er zurück in die Datei geleitet und kann diese jetzt herunterladen.

Vorbildlichdl-file.php .

Ähnliches finden Sie in \wp-includes\ms-files.phpIhrer WordPress-Installation, jedoch für Multisite-Anwendungen ohne Login-Prüfung und Weiterleitung.

Je nachdem , wie viel Verkehr Sie haben, könnte es klug sein , dies zu einer besseren Integration mit Ihrem Server, zB X-Accel-Redirectoder X-SendfileHeader.

hakre
quelle
1
Wie passe ich dl-file.php an, wenn ich Dateien in einem Unterverzeichnis wie wp-content / uploads / secure speichern möchte?
Dies ist die einzige wirklich sichere Lösung. Alles andere, was Sie im Web finden können, wie das Überprüfen des Referrer-Headers, das Überprüfen von Cookies und das Deaktivieren der Verzeichnisliste, ist eine halbe Sache, da Sie HTTP-Anforderungsheader leicht fälschen können, um es zu umgehen.
Luke
Leute ... das schien die perfekte Lösung für mich zu sein. Das Problem ist, dass ich PDFJS von Mozilla verwende, um auf einige PDFs aus dem Upload-Ordner zuzugreifen. PDFJS verwendet Teil-Content-Header, um nur die Seiten zu erhalten, an denen ich interessiert bin. .so ist diese Lösung ein No Goer für mich. irgendwelche Vorschläge??
Otto Nascarella
@OttoNascarella: Partielle Content-Anfragen an PHP wurden ab heute gelöst, dies ist unabhängig von dieser WordPress-Frage. Tatsächlich ist die Frage schon ziemlich alt: Wiederaufsetzbare Downloads, wenn die Datei mit PHP gesendet wird?
Hakre
@hakre Was ist mit einigen Bildern, die auf der Startseite der Website verwendet werden, und mit denen, die Benutzer besuchen? Es gibt mir 404 Fehler, wenn ich nicht angemeldet bin.
Dhaval Panchal
14

Sie können ein Plugin auch mit dem initHook und dem get-value schreiben $_GET[ 'file' ];. Wenn der Benutzer diesen get-Wert hat, springen Sie in eine Funktion, um die Zugriffsrechte für die Dateien zu überprüfen: Zum Beispiel mit einem Kontrollkästchen in einer 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' ] );
    }
}

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

Sie können auch eine benutzerdefinierte URL für Dateien über den Hook hinzufügen 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
quelle
Das hat auf meiner Seite nicht funktioniert, weiß jemand warum? Ich kopiere genau.
Ryan S
Schutz funktioniert nur pdf. andere Dateierweiterung funktioniert nicht wie: doc, docx, jpg und etc ...
Patel
1

Wenn Sie einen Plug-in-basierten Ansatz zur Lösung dieses Problems wünschen, finden Sie hier eine einigermaßen gute Lösung, die ich (endlich) gefunden habe:

  1. Installieren Sie das Plugin 'Download Monitor', verfügbar unter:
    https://wordpress.org/plugins/download-monitor/
  2. Gehen Sie im WordPress-Dashboard zum neuen Menüpunkt "Downloads" und fügen Sie einen neuen "Download" hinzu, wie auf der Plugin-Dokumentations-Website hier beschrieben: https://www.download-monitor.com/kb/adding-downloads/ . Beachten Sie den für Sie bereitgestellten 'Download'-Shortcode (z. B. auf dem Merkzettel speichern). Beachten Sie, dass die Datei in gespeichert wird/wp-content/uploads/dlm_uploads/
  3. Geben Sie in der Metabox "Download-Optionen" "Nur für Mitglieder" an (siehe https://www.download-monitor.com/kb/download-options/ ) und klicken Sie auf "Veröffentlichen".
  4. Fügen Sie auf der Seite, auf der nur der Download für Mitglieder angezeigt werden soll, den in Schritt 2 notierten Shortcode hinzu und 'Veröffentlichen / Aktualisieren' Sie die Seite, wie hier dokumentiert: https://www.download-monitor.com / kb / shortcode-download / . Sie können die Vorlage für den Download-Link wie hier beschrieben ändern: https://www.download-monitor.com/kb/content-templates/ oder eine eigene Vorlage erstellen (z. B. um die Anzahl der Downloads zu entfernen).
  5. Wenn Sie zu Ihrer Seite navigieren, sollte ein Download-Link angezeigt werden (der jedoch nicht die URL der Download-Datei enthält). Wenn Sie in einem neuen Browserfenster (oder Inkognito-Fenster) zur gleichen Seite navigieren, sollten Sie feststellen, dass der Download nicht mehr funktioniert.

Dies bedeutet, dass jeder, der nicht angemeldet ist, die Datei weder herunterladen noch die tatsächliche URL der Datei anzeigen kann. Falls jemand die URL der Datei nicht kennt, stoppt das Plugin auch das Surfen der Benutzer zur URL der realen Datei, indem der Zugriff auf den /wp-content/uploads/dlm_uploads/Ordner gesperrt wird.

Bonus: Wenn Sie dies für eine Site tun, auf der sich Benutzer nur als "Mitglieder" anmelden dürfen (aber keine WordPress-Berechtigungen wie zum Beispiel zum Bearbeiten von Seiten oder als Administrator haben), installieren Sie das Plugin "Mitglieder" https: // wordpress .org / plugins / members / , erstelle eine neue Benutzerrolle mit dem Namen 'Member' und gib ihr die einmalige Funktion 'Lesen', erstelle einen neuen Benutzer in WordPress und stelle sicher, dass du ihnen die Rolle 'Member' gibst.

Wenn Sie den Inhalt von Seiten schützen möchten, bietet das Plugin "Mitglieder" einige Optionen oder es gibt andere Plugins. Wenn Sie möchten, dass die Anmeldeseite für Mitglieder besser aussieht als das WordPress-Standard-Anmeldeformular, verwenden Sie etwas wie "Meine Anmeldung": https://wordpress.org/plugins/theme-my-login/

Matty J
quelle
Der Prozess, den ich oben beschrieben habe, wird auch hier erklärt, obwohl Sie sehen können, dass er nicht nur für PDFs spezifisch sein muss: thedigitalcrowd.com/website-development/wordpress/…
Matty J