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
.htaccess
para 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
.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 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 .htaccess
arquivo 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/conf
e 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.php
em branco dentro de cada filho da pasta protegida para impedir a navegação - mas isso deve ser evitado pelas .htaccess
regras 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.