Recientemente tuve un problema relacionado y escribí este artículo al respecto .
Supondré que las descargas se cargan a través del manejo de medios de WordPress o, de lo contrario, tendrá un ID de archivo adjunto para la descarga.
Esquema de la solución
- Haga que el directorio de cargas sea 'seguro' (en este sentido, solo significa usar
.htaccess
para bloquear cualquier intento de acceso directo a los archivos en el directorio de cargas (o un subdirectorio del mismo), por ejemplo, a través de mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf
)
- Cree un enlace de descarga que incluya el ID del archivo adjunto: esto pasa por WordPress para verificar que el permiso del usuario para ver el archivo adjunto permite / niega el acceso.
Advertencias
-
Esto hace uso de
.htaccess
para proporcionar seguridad . Si esto no está disponible / activado (servidores nginx por ejemplo), entonces no obtendrá mucha seguridad. Puede evitar que el usuario navegue por el directorio de uplods. Pero el acceso directo funcionará.
- Según lo anterior. Esto no debe usarse en la distribución si necesita seguridad absoluta . Está bien si su configuración específica funciona, pero en general, no se puede garantizar. Mi artículo vinculado en parte está tratando de abordar esto.
-
Perderás miniaturas . El bloqueo del acceso directo a una carpeta o subcarpeta significará que no se pueden ver las miniaturas de los archivos en esa carpeta. Mi artículo vinculado está intentando en parte tratar esto.
Bloqueo de acceso directo
Para hacer esto en su carpeta de subidas (o en una subcarpeta, todo el material confidencial debe residir, a cualquier profundidad, dentro de esta carpeta). Coloque un archivo .htaccess
con lo siguiente:
Order Deny,Allow
Deny from all
A continuación, asumo que adjuntará material confidencial para publicar el tipo "cliente". Cualquier medio cargado en la página de edición del cliente se almacenará en la carpeta uploads/conf/
La función para configurar el directorio de subidas protegidas
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.
}
Subiendo material confidencial
/**
* 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' );
}
}
}
Una vez hecho esto, el contenido cargado debe estar dentro de uploads/conf
y tratar de acceder a él directamente desde tu navegador no debería funcionar.
Descarga de contenido
Esto es fácil. La url de descarga puede ser algo www.site.com?wpse26342download=5
(donde 5 es el ID de adjunto del contenido cargado). Usamos esto para identificar el archivo adjunto, verificar los permisos del usuario actual y permitir que se descarguen.
Primero, configura la variable de consulta
/**
* 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;
}}
Ahora configure un escucha para (tal vez) activar la descarga ...
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;
}
Comentarios finales
El código anterior puede contener errores / errores de sintaxis y no se ha probado, y lo usa bajo su propio riesgo :).
El url de descarga puede ser "prettified" usando reescrituras. Como se indica en los comentarios, puede agregar un index.php
en blanco dentro de cada elemento secundario de la carpeta protegida para evitar la exploración, pero esto debería evitarse con las reglas .htaccess
de todos modos.
Un método más seguro sería almacenar los archivos públicos fuera de un directorio público. O en un servicio externo como Amazon S3. Para esto último, deberá generar una URL válida para recuperar el archivo de Amazon (usando su clave privada). Ambos requieren un cierto nivel de confianza en su servicio de Host / tercero.
Desconfiaba del uso de complementos que sugieran que ofrecen "descargas protegidas". No he encontrado ninguno que ofrezca suficiente seguridad. Por favor, no las advertencias de esta solución también, y agradecería cualquier sugerencia o crítica.