Recentemente, tive um problema relacionado e escrevi este artigo sobre ele .
Suponho que os downloads sejam enviados por meio da manipulação de mídia do WordPress - ou você tem um ID de anexo para o download.
Esboço da solução
- Torne o diretório de uploads 'seguro' (nesse sentido, apenas quero dizer usar
.htaccesspara bloquear qualquer tentativa de acessar diretamente os arquivos no diretório de uploads (ou um subdiretório) - 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 a permissão do usuário para visualizar o anexo permite / nega acesso.
Ressalvas
- Isso faz uso
.htaccesspara fornecer segurança . Se isso não estiver disponível / ativado (servidores nginx, por exemplo), você não terá muita segurança. Você pode impedir 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 sua configuração específica funcionar - mas, em geral, não pode ser garantida. Meu artigo vinculado está em parte tentando resolver isso.
- Você perderá miniaturas . Bloquear o acesso direto a uma pasta ou subpasta significa que as miniaturas dos arquivos dessa pasta não podem ser exibidas. Meu artigo vinculado está em parte tentando resolver isso.
Bloqueando o acesso direto
Para fazer isso na sua pasta de uploads (ou em uma subpasta - todo o material confidencial deve residir, a qualquer profundidade, dentro desta pasta). Coloque um .htaccessarquivo com o seguinte:
Order Deny,Allow
Deny from all
A seguir, suponho que você anexará material confidencial ao tipo de postagem 'cliente'. Qualquer mídia carregada na página de edição do cliente será armazenada na uploads/conf/pasta
A função para configurar o diretório de uploads protegidos
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 uploads/confe a tentativa de acessá-lo diretamente usando o navegador não deve funcionar.
Download de conteúdo
Isso é facil. O URL do download pode ser algo www.site.com?wpse26342download=5(em que 5 é o ID do anexo do conteúdo carregado). 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 utiliza por sua própria conta e risco :).
O URL do download pode ser "pré-modificado" usando reescritas. Conforme declarado nos comentários, você pode adicionar um espaço index.phpem branco dentro de cada filho da pasta protegida para impedir a navegação - mas isso deve ser evitado pelas .htaccessregras 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 o ú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 no seu host / serviço de terceiros.
Eu ficaria cauteloso ao usar quaisquer plug-ins que sugiram que eles oferecem 'downloads protegidos'. Não encontrei nenhum que ofereça 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.