Bagaimana cara membatasi unduhan lampiran ke pengguna tertentu?

12

Saya memiliki kasus penggunaan yang sangat spesifik di mana situs yang dibuat untuk pengacara dan setiap kliennya dapat login ke 'halaman / portal khusus' mereka sendiri (jenis posting khusus) tanpa kemampuan untuk mengakses wp-admin dll. (Saya membuat semua halaman login / register / pengeditan profil di ujung depan). Di halaman / portal ini pengacara akan meninggalkan pesan dan file untuk diunduh klien , sekarang secara teoritis, satu klien dapat menebak (atau jika memiliki pengetahuan tentang file klien lain) nama file lain dan mengunduh kemudian dengan demikian menciptakan masalah dengan privasi / keamanan / materi rahasia dll.

Saya mencari ide / konsep untuk solusi, pemikiran awal saya adalah memiliki titik tautan unduhan ke beberapa download.php mengirimkan id lampiran, id pengguna, halaman / id portal dan nonce dan di sisi lain memprosesnya. .

Bagaimana menurut anda? Apakah saya di jalur yang benar atau pendekatan ini cacat?

Terima kasih!

Amit
sumber
Sudahkah Anda menemukan solusi untuk ini?
brasofilo
@brasofilo, no ..
Amit

Jawaban:

6

Yang perlu terjadi adalah bahwa Anda perlu mem-proxy permintaan unduhan untuk jenis file yang Anda inginkan melalui WordPress. Mari kita asumsikan Anda akan membatasi akses ke file ".doc".

1. Tetapkan variabel kueri yang menunjukkan file yang diminta

function add_get_file_query_var( $vars ) {
    $vars[] = 'get_file';
    return $vars;
}
add_filter( 'query_vars', 'add_get_file_query_var' );

2. Perbarui .htaccess untuk meneruskan permintaan file terbatas ke WordPress

Ini akan menangkap permintaan ke file yang ingin Anda batasi dan mengirimkannya kembali ke WordPress menggunakan variabel kueri khusus di atas. Masukkan aturan berikut sebelum RewriteCondbaris.

RewriteRule ^wp-content/uploads/(.*\.docx)$ /index.php?get_file=$1

3. Menangkap nama file yang diminta dalam variabel kueri khusus; dan verifikasi akses ke file:

function intercept_file_request( $wp ) {
    if( !isset( $wp->query_vars['get_file'] ) )
        return;

    global $wpdb, $current_user;

    // Find attachment entry for this file in the database:
    $query = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid='%s'", $_SERVER['REQUEST_URI'] );
    $attachment_id = $wpdb->get_var( $query );

    // No attachment found. 404 error.  
    if( !$attachment_id ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Get post from database 
    $file_post = get_post( $attachment_id );
    $file_path = get_attached_file( $attachment_id );

    if( !$file_post || !$file_path || !file_exists( $file_path ) ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Logic for validating current user's access to this file...
    // Option A: check for user capability
    if( !current_user_can( 'required_capability' ) ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Option B: check against current user
    if( $current_user->user_login == "authorized_user" ) {
        $wp->query_vars['error'] = '404';
        return;
    }

    // Everything checks out, user can see this file. Simulate headers and go:
    header( 'Content-Type: ' . $file_post->post_mime_type );
    header( 'Content-Dispositon: attachment; filename="'. basename( $file_path ) .'"' );
    header( 'Content-Length: ' . filesize( $file_path ) );

    echo file_get_contents( $file_path );
    die(0);
}
add_action( 'wp', 'intercept_file_request' );

NB Solusi ini hanya berfungsi untuk pemasangan satu situs ! Ini karena WordPress MU sudah meneruskan permintaan file yang diunggah melalui sub-situs wp-includes/ms-files.php. Ada solusi untuk WordPress MU juga, tetapi sedikit lebih terlibat.

Bendoh
sumber
Hai, saya tidak melihat bahwa Anda mengaitkan fungsi ini pada langkah intercept_file_requestatau yang dipanggil di mana saja, bagaimana fungsi itu dipecat?
Bobz
Poin bagus, itu harus dikaitkan wp, saya sudah memperbarui contoh.
Bendoh
3

Saya baru-baru ini memiliki masalah terkait dan menulis artikel ini tentang itu .

Saya akan menganggap bahwa unduhan diunggah melalui penanganan media WordPress - atau Anda memiliki ID lampiran untuk unduhan.

Garis besar solusi

  • Jadikan direktori unggahan 'aman' (Dalam hal ini, saya hanya bermaksud menggunakan .htaccessuntuk memblokir segala upaya untuk secara langsung mengakses file dalam direktori unggahan (atau sub-direktori daripadanya) - misalnya via mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)
  • Buat tautan unduhan termasuk ID lampiran - ini melewati WordPress untuk memeriksa izin pengguna untuk melihat izin lampiran / menolak akses.

Peringatan

  • Ini memanfaatkan .htaccessuntuk memberikan keamanan . Jika ini tidak tersedia / dihidupkan (server nginx misalnya), maka Anda tidak akan mendapatkan banyak keamanan. Anda dapat mencegah pengguna menelusuri direktori uplods. Tetapi akses langsung akan bekerja.
  • Seperti di atas. Ini tidak boleh digunakan dalam distribusi jika Anda memerlukan keamanan mutlak . Tidak masalah jika pengaturan khusus Anda berfungsi - tetapi secara umum, itu tidak dapat dijamin. Artikel tertaut saya sebagian mencoba mengatasi ini.
  • Anda akan kehilangan thumbnail . Memblokir akses langsung ke folder atau sub-folder akan berarti thumbnail file dalam folder itu tidak dapat dilihat. Artikel tertaut saya sebagian berusaha untuk mengatasi ini.

Memblokir akses langsung

Untuk melakukan ini di folder unggahan Anda (atau subfolder - semua materi rahasia harus berada, di kedalaman apa pun, di dalam folder ini). Tempatkan .htaccessfile dengan yang berikut ini:

Order Deny,Allow
Deny from all

Berikut ini saya berasumsi bahwa Anda akan melampirkan materi rahasia ke jenis posting 'klien'. Setiap media yang diunggah pada halaman edit klien akan disimpan dalam uploads/conf/folder

Fungsi untuk mengatur direktori unggahan yang dilindungi

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.
}

Mengunggah materi rahasia

   /**
    * 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' );
                }
        }

    }

Setelah melakukan itu, konten yang diunggah harus berada di dalam uploads/confdan mencoba mengaksesnya langsung menggunakan browser Anda seharusnya tidak berfungsi.

Mengunduh Konten

Ini mudah. Url unduhan dapat berupa sesuatu www.site.com?wpse26342download=5(di mana 5 adalah ID lampiran dari konten yang diunggah). Kami menggunakan ini untuk mengidentifikasi lampiran, memeriksa izin pengguna saat ini dan memungkinkan mereka untuk mengunduh.

Pertama, atur variabel kueri

/**
 * 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;
}}

Sekarang siapkan pendengar untuk (mungkin) memicu unduhan ...

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;
}

Komentar terakhir

Kode di atas mungkin mengandung kesalahan bug / sintaksis dan belum diuji, dan Anda menggunakannya dengan risiko Anda sendiri :).

URL unduhan dapat 'dipoles' menggunakan penulisan ulang. Seperti yang dinyatakan dalam komentar Anda dapat menambahkan kosong index.phpdi dalam setiap anak folder yang dilindungi untuk mencegah penjelajahan - tetapi ini harus dicegah dengan .htaccessaturan.

Metode yang lebih aman adalah menyimpan file publik di luar direktori publik. Atau pada layanan eksternal seperti Amazon S3. Untuk yang terakhir Anda harus membuat url yang valid untuk mengambil file dari Amazon (menggunakan kunci pribadi Anda). Kedua hal ini membutuhkan tingkat kepercayaan tertentu pada Host / layanan pihak ketiga Anda.

Saya akan khawatir menggunakan plug-in yang menyarankan mereka menawarkan 'unduhan yang dilindungi'. Saya belum menemukan yang memberikan keamanan yang cukup baik. Tolong jangan peringatan dari solusi ini juga - dan saya akan menyambut setiap saran atau kritik.

Stephen Harris
sumber
1

Mungkin, Anda mungkin sudah tahu trik ini, Kode ini akan memeriksa nama pengguna yang masuk saat ini dan jika cocok akan menampilkan tautan unduhan ke file itu, kalau tidak, ia tidak akan menampilkan apa pun.

ini kodenya:

<?php 
    global $current_user;
    get_currentuserinfo();

    if ( 'username' == $current_user->user_login ) {
        echo 'Download Link';
    } else {
        // nothing
    }
?>

Namun, ini bukan pendekatan yang baik, karena file disimpan di server, siapa pun yang memiliki tautan dapat mengunduh file itu.

ya
sumber
0

Saya kira informasi ini bersifat rahasia dan karena itu selain menyembunyikan tautan ke file Anda ingin membuatnya benar-benar tidak dapat diakses sepenuhnya oleh siapa pun di web, bahkan jika mereka menebak URL, kecuali jika pengguna tersebut memiliki izin eksplisit untuk mengunduh file.

Lihatlah ke penyimpanan file di Amazon S3 dengan aman dan kemudian berikan URL yang sudah ditandatangani sebelumnya (terbatas waktu) untuk file asalkan pemeriksaan keamanan yang benar telah dipenuhi (yaitu, pengguna telah masuk ke situs Anda dan seperti yang mereka katakan).

Ada AWS SDK yang sangat bagus yang membuatnya sangat mudah untuk melakukan ini.

Yang perlu Anda teliti adalah bagaimana mengirim file yang diunggah melalui antarmuka unggah WP ke S3 sebagai gantinya, sebagai alternatif buat pengunggah Anda sendiri .

Pilihan lain adalah melihat kode WP e-commerce . Mereka menawarkan pengunduhan aman file perangkat lunak (misalnya MP3). Saya percaya file dikonversi menjadi hash dengan kunci enkripsi yang dihasilkan per pengguna saat pembelian. Ini akan membutuhkan beberapa penguraian untuk melihat cara kerjanya, tetapi prosesnya tidak akan unik untuk plugin ini sehingga contoh lain akan tersedia (di suatu tempat).

deadlyhifi
sumber
0

Saya pikir enkripsi file adalah cara untuk pergi seperti jawaban di atas. Ada plugin di Wordpress.org yang memungkinkan Anda melindungi unduhan. http://wordpress.org/extend/plugins/download-protect/ Anda dapat menggunakan layanan Amazon atau google drive juga. Ada banyak layanan yang menawarkan unduhan yang dilindungi seperti drop box juga.

Chris
sumber
keamanan melalui ketidakjelasan adalah pendekatan yang buruk. siapa pun akan dapat melihat permintaan http dan mendapatkan url dengan cara ini.
mulllhausen