Niedawno miałem podobny problem i napisałem o tym artykuł .
Zakładam, że pliki do pobrania są przesyłane za pomocą obsługi multimediów WordPress - w przeciwnym razie masz identyfikator załącznika do pobrania.
Zarys rozwiązania
- Ustaw katalog przesyłania jako „bezpieczny” (w tym sensie mam na myśli jedynie
.htaccess
blokowanie wszelkich prób bezpośredniego dostępu do plików w katalogu przesyłania (lub jego podkatalogu) - np. Przez mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf
)
- Utwórz link do pobrania zawierający identyfikator załącznika - przechodzi on przez WordPress, aby sprawdzić uprawnienia użytkownika do przeglądania załącznika zezwala / odmawia dostępu.
Ostrzeżenia
- Wykorzystuje to w
.htaccess
celu zapewnienia bezpieczeństwa . Jeśli nie jest to dostępne / włączone (na przykład serwery Nginx), nie uzyskasz większego bezpieczeństwa. Możesz uniemożliwić użytkownikowi przeglądanie katalogu uplods. Ale bezpośredni dostęp będzie działał.
- Jak wyżej Nie należy tego używać w dystrybucji, jeśli wymaga się absolutnego bezpieczeństwa . Jest w porządku, jeśli twoja konfiguracja działa, ale ogólnie nie można tego zagwarantować. Mój link do artykułu częściowo próbuje rozwiązać ten problem.
- Utracisz miniatury . Zablokowanie bezpośredniego dostępu do folderu lub podfolderu oznacza, że nie można wyświetlić miniatur plików w tym folderze. Mój link do artykułu częściowo próbuje rozwiązać ten problem.
Blokowanie bezpośredniego dostępu
Aby to zrobić w folderze przesyłania (lub w podfolderze - wszystkie poufne materiały muszą znajdować się na dowolnej głębokości w tym folderze). Umieść .htaccess
plik z następującymi danymi:
Order Deny,Allow
Deny from all
Poniżej zakładam, że będziesz dołączać poufne materiały do postu typu „klient”. Wszelkie media przesłane na stronę edycji klienta będą przechowywane w uploads/conf/
folderze
Funkcja konfiguracji chronionego katalogu przesyłania
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.
}
Przesyłanie poufnych materiałów
/**
* 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' );
}
}
}
Po wykonaniu tej czynności przesłane treści powinny znajdować się w środku, uploads/conf
a próba uzyskania do nich bezpośredniego dostępu za pomocą przeglądarki nie powinna działać.
Pobieranie zawartości
To jest łatwe. Adres URL pobierania może być czymś www.site.com?wpse26342download=5
(gdzie 5 to identyfikator załącznika przesłanej treści). Używamy tego do identyfikacji załącznika, sprawdzania uprawnień bieżącego użytkownika i umożliwienia mu pobrania.
Najpierw skonfiguruj zmienną zapytania
/**
* 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;
}}
Teraz skonfiguruj detektor, aby (być może) uruchamiał pobieranie ...
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;
}
Komentarze końcowe
Powyższy kod może zawierać błędy / błędy składniowe i jest nieprzetestowany i używasz go na własne ryzyko :).
Adres URL pobierania można „wstępnie zapisać” za pomocą przepisywania. Jak stwierdzono w komentarzach, możesz dodać puste miejsce index.php
w każdym podrzędnym chronionym folderze, aby zapobiec przeglądaniu - ale i tak powinny temu zapobiec .htaccess
reguły.
Bardziej bezpieczną metodą byłoby przechowywanie plików publicznych poza katalogiem publicznym. Lub w usłudze zewnętrznej, takiej jak Amazon S3. W przypadku tego ostatniego musisz wygenerować prawidłowy adres URL, aby pobrać plik z Amazon (używając klucza prywatnego). Oba wymagają pewnego poziomu zaufania do usług hosta / strony trzeciej.
Byłbym ostrożny wobec używania jakichkolwiek wtyczek, które sugerują, że oferują „chronione pliki do pobrania”. Nie znalazłem żadnych, które zapewniają wystarczająco dobre bezpieczeństwo. Proszę również nie brać pod uwagę tego rozwiązania - i chętnie przyjmę wszelkie sugestie lub krytykę.