¿Cómo proteger las cargas si el usuario no ha iniciado sesión?

80

Uso wordpress para un sitio privado donde los usuarios cargan archivos. Utilizo el "WordPress privado" para evitar el acceso al sitio si el usuario no está conectado.

Me gustaría hacer lo mismo con los archivos cargados en la carpeta de cargas.

Por lo tanto, si un usuario no ha iniciado sesión, no podrá acceder a: https://xxxxxxx.com/wp-content/uploads/2011/12/xxxxxxx.pdf si intenta acceder pero no está registrado, entonces debería ser redirigido a la página de inicio de sesión, por ejemplo.

Encontré un complemento llamado archivos privados, pero la última vez que lo actualicé fue en 2009 y parece que no funciona en mi wordpress.

Alguien sabe algún método? ¿El método de hotlinking será suficiente para proteger esto?

También encontré este método:

# 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

Pero entonces, ¿cualquier usuario que replique la cookie podría pasar esto bien? Saludos

chifliiiii
fuente
1
¿Alguna razón por la que no puede usar un directorio de carga diferente, como uno fuera de la raíz del sitio?
onetrickpony
En realidad no, pero ya tengo toneladas de archivos adjuntos a las publicaciones en ese directorio, no me importa moverme si puedo encontrar una solución adecuada
chifliiiii

Respuestas:

86

Solo verificar si la cookie existe, no es una protección estricta.

Para obtener una protección más sólida, puede pasar o "proxy" todas las solicitudes a la carpeta cargada (a modo de ejemplo uploadsen el siguiente ejemplo) a través de un script php:

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

Todas las solicitudes de archivos cargados (que incluye imágenes en publicaciones) irían a lo dl-file.phpque luego se puede verificar si el usuario ha iniciado sesión o no.

Si el usuario no ha iniciado sesión, se mostrará el formulario de inicio de sesión de su sitio. Después de que el usuario inicie sesión, será redirigida de nuevo al archivo y puede descargarlo ahora.

Ejemplardl-file.php .

Algo similar se puede encontrar en \wp-includes\ms-files.phpsu instalación de WordPress, pero esa es para múltiples sitios y sin la verificación de inicio de sesión y redireccionamientos.

Dependiendo de la cantidad de tráfico que tenga, podría ser conveniente integrarlo mejor con su servidor, por ejemplo, X-Accel-Redirecto X-Sendfileencabezados.

hakre
fuente
1
¿Cómo ajusto dl-file.php si quiero almacenar archivos en un subdirectorio como wp-content / uploads / secure?
Esta es la única solución realmente segura. Cualquier otra cosa que pueda encontrar en la web, como verificar el encabezado del árbitro, verificar las cookies, no permitir el listado del directorio, es una medida a medias, ya que puede falsificar fácilmente los encabezados de solicitudes HTTP para evitarlo.
Lucas
Chicos ... esto parecía la solución perfecta para mí ... el problema es que estoy usando PDFJS de Mozilla para acceder a algunos archivos PDF desde la carpeta de carga, y PDFJS usa encabezados de contenido parcial para obtener solo las páginas que le interesan ... .so esta solución no es fácil para mí. ¿¿alguna sugerencia??
Otto Nascarella
@OttoNascarella: las solicitudes de contenido parcial a PHP se han resuelto a partir de hoy, esto es independiente de esta pregunta de WordPress. De hecho, la pregunta ya es bastante antigua: ¿Descargas reanudables cuando se usa PHP para enviar el archivo?
hakre
@hakre ¿Qué pasa con algunas de esas imágenes utilizadas en la página principal del sitio web y cualquier usuario que visite el sitio? Me da error 404 si no estoy conectado.
Dhaval Panchal,
14

También puede escribir un complemento utilizando el initgancho y el valor de obtención $_GET[ 'file' ];. Si el usuario tiene este valor de obtención, ingrese a una función para verificar los derechos de acceso a los archivos: por ejemplo, con una casilla de verificación en una 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' ] );
    }
}

la función 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();
}

También puede agregar una URL personalizada para archivos a través del gancho 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
fuente
Esto no funcionó de mi lado, ¿alguien sabe por qué? Copio exactamente.
Ryan S
Protección trabajando solo pdf. la extensión de otros archivos no funciona como: doc, docx, jpg y etc ...
Patel
1

Si desea un enfoque basado en complementos para resolver este problema, aquí hay una solución razonablemente buena que he encontrado (finalmente):

  1. Instale el complemento 'Descargar Monitor', disponible en:
    https://wordpress.org/plugins/download-monitor/
  2. En el Panel de WordPress, vaya al nuevo elemento del menú 'Descargas' y agregue una nueva 'Descarga', como se describe en el sitio web de documentación del complemento aquí: https://www.download-monitor.com/kb/adding-downloads/ . Tome nota del shortcode 'Descargar' que se le proporciona (por ejemplo, guardar en el Bloc de notas). Tenga en cuenta que el archivo se guarda en/wp-content/uploads/dlm_uploads/
  3. En el metabox 'Opciones de descarga', especifique 'Solo miembros' (como se documenta aquí https://www.download-monitor.com/kb/download-options/ ) y haga clic en 'Publicar'.
  4. En la página que desea que aparezcan las descargas solo para miembros, agregue el código abreviado del que tomó nota en el paso 2 y 'Publique / Actualice' la página, como se documenta aquí: https://www.download-monitor.com / kb / shortcode-download / . Puede cambiar la plantilla de enlace de descarga como se describe aquí https://www.download-monitor.com/kb/content-templates/ , o crear la suya propia (por ejemplo, para eliminar el 'conteo' de descargas)
  5. Navegue a su página, debería ver un enlace de descarga (pero que no revela la URL del archivo de descarga). Si navega a la misma página en una nueva ventana del navegador (o ventana de incógnito), debería encontrar que la descarga ya no funciona.

Esto significa que cualquier persona que no haya iniciado sesión no puede descargar el archivo ni ver la URL real del archivo. Si en el caso de que alguien no autorizado descubra la URL del archivo, el complemento también impide que los usuarios naveguen hacia la URL del archivo real al bloquear el acceso a la /wp-content/uploads/dlm_uploads/carpeta.

Bonificación: si está haciendo esto para un sitio donde necesita que los usuarios puedan iniciar sesión solo como 'Miembros' (pero no tienen permisos de WordPress como editar páginas o ser un Administrador), instale el complemento 'Miembros' https: // wordpress .org / plugins / members / , cree un nuevo rol de usuario llamado 'Miembro' y dele la capacidad única de 'leer', cree un nuevo Usuario en WordPress y asegúrese de asignarle un rol de 'Miembro'.

Si desea proteger el contenido de las páginas, el complemento 'Miembros' ofrece algunas opciones, o existen otros complementos disponibles. Si desea crear un tema en la página de inicio de sesión para que los Miembros se vean mejor que el formulario de inicio de sesión predeterminado de WordPress, use algo como 'Theme My Login': https://wordpress.org/plugins/theme-my-login/

Matty J
fuente
El proceso que describí anteriormente también se explica aquí, aunque como puede ver, no tiene que ser específico solo para archivos PDF: thedigitalcrowd.com/website-development/wordpress/…
Matty J