Recientemente tuve un problema relacionado y escribí este artículo al respecto .
Asumiré que las descargas se cargan a través del manejo de medios de WordPress, o de lo contrario tiene una ID de archivo adjunto para la descarga.
Esquema de la solución
- Hacer que el directorio de archivos 'seguro' (en este sentido que acaba de utilización media
.htaccess
de bloquear cualquier intento de acceso de los archivos directamente en el directorio de archivos (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 la 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 se utiliza
.htaccess
para proporcionar seguridad . Si esto no está disponible / activado (servidores nginx, por ejemplo), entonces no obtendrá mucha seguridad. Puede evitar que el usuario explore el directorio uplods. Pero el acceso directo funcionará.
- Según lo anterior. Esto no debe usarse en la distribución si requiere seguridad absoluta . Está bien si su configuración específica funciona, pero en general, no se puede garantizar. Mi artículo vinculado está tratando en parte de abordar esto.
- Perderás miniaturas . Bloquear el 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 intenta en parte abordar esto.
Bloqueo de acceso directo
Para hacer esto en su carpeta de cargas (o una subcarpeta, todo el material confidencial debe residir, a cualquier profundidad, dentro de esta carpeta). Coloque un .htaccess
archivo con lo siguiente:
Order Deny,Allow
Deny from all
A continuación, supongo 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 uploads/conf/
carpeta
La función para configurar el directorio de cargas 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.
}
Subir 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 debería estar dentro uploads/conf
y no debería funcionar intentar acceder directamente a él utilizando su navegador.
Descargando contenido
Esto es facil. La URL de descarga puede ser algo www.site.com?wpse26342download=5
(donde 5 es la ID de archivo adjunto del contenido cargado). Usamos esto para identificar el archivo adjunto, verificar los permisos del usuario actual y permitir que se descarguen.
Primero, configure 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 oyente para (quizás) 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 :).
La URL de descarga se puede 'prettificar' usando reescrituras. Como se indica en los comentarios, puede agregar un espacio index.php
en blanco dentro de cada elemento secundario de la carpeta protegida para evitar la exploración, pero esto debería evitarse de .htaccess
todas formas.
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 (utilizando su clave privada). Ambos requieren un cierto nivel de confianza en su servicio de Host / tercero.
Sería cauteloso sobre el uso de complementos que sugieran que ofrecen 'descargas protegidas'. No he encontrado ninguno que brinde suficiente seguridad. Por favor, no las advertencias de esta solución también, y agradecería cualquier sugerencia o crítica.