Recentemente tive um problema relacionado e escrevi este artigo sobre ele .
Assumirei que os downloads são enviados por meio do manuseio de mídia do WordPress - ou, caso contrário, você tem um ID de anexo para o download.
Esboço da solução
- Tornar o diretório de uploads 'seguro' (nesse sentido, apenas significa usar
.htaccess
para bloquear qualquer tentativa de acessar diretamente os arquivos no diretório de uploads (ou um subdiretório deles) - por exemplo via mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf
)
- Crie um link para download incluindo o ID do anexo - isso passa pelo WordPress para verificar se a permissão do usuário para visualizar o anexo permite / nega acesso.
Advertências
-
Isso faz uso de
.htaccess
para fornecer segurança . Se isso não estiver disponível / ativado (servidores nginx, por exemplo), você não terá muita segurança. Você pode evitar que o usuário navegue no diretório uplods. Mas o acesso direto funcionará.
- conforme acima. Isso não deve ser usado na distribuição se você precisar de segurança absoluta . Tudo bem se a sua configuração específica funcionar - mas, em geral, não pode ser garantida. Meu artigo vinculado está, em parte, tentando abordar isso.
-
Você perderá miniaturas . Bloquear o acesso direto a uma pasta ou subpasta significa que as miniaturas dos arquivos nessa pasta não podem ser visualizadas. Meu artigo vinculado está, em parte, tentando abordar isso.
Bloqueio de acesso direto
Para fazer isso na sua pasta de uploads (ou em uma subpasta, todo material confidencial deve residir, em qualquer profundidade, dentro dessa pasta). Coloque um arquivo .htaccess
com o seguinte:
Order Deny,Allow
Deny from all
A seguir, suponho que você esteja anexando material confidencial para postar o tipo 'cliente'. Qualquer mídia carregada na página de edição do cliente será armazenada na pasta uploads/conf/
A função para configurar o diretório de uploads protegido
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.
}
Upload de 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' );
}
}
}
Feito isso, o conteúdo carregado deve estar dentro de uploads/conf
e tentar acessá-lo diretamente usando seu navegador não deve funcionar.
Download de conteúdo
Isso é fácil. O URL de download pode ser algo em www.site.com?wpse26342download=5
(onde 5 é o ID do anexo do conteúdo enviado). Usamos isso para identificar o anexo, verificar as permissões do usuário atual e permitir o download.
Primeiro, configure a variável 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;
}}
Agora, configure um ouvinte para (talvez) acionar o download ...
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;
}
Comentários finais
O código acima pode conter erros de bugs / sintaxe e não foi testado, e você o usa por sua conta e risco :).
O URL de download pode ser 'embelezado' usando reescrevê-lo. Conforme declarado nos comentários, você pode adicionar um index.php
em branco dentro de cada filho da pasta protegida para impedir a navegação - mas isso deve ser impedido pelas regras .htaccess
de qualquer maneira.
Um método mais seguro seria armazenar os arquivos públicos fora de um diretório público. Ou em um serviço externo como o Amazon S3. Para este último, você precisará gerar um URL válido para buscar o arquivo da Amazon (usando sua chave privada). Ambos exigem um certo nível de confiança em seu host / serviço de terceiros.
Eu ficaria preocupado em usar plug-ins que sugiram oferecer "downloads protegidos". Eu não encontrei nenhum que fornecesse segurança suficiente. Por favor, não as advertências desta solução também - e eu gostaria de receber sugestões ou críticas.