วิธี จำกัด การดาวน์โหลดไฟล์แนบให้กับผู้ใช้ที่เฉพาะเจาะจง


12

ฉันมีกรณีการใช้งานที่เฉพาะเจาะจงซึ่งเว็บไซต์สร้างขึ้นสำหรับนักกฎหมายและลูกค้าของเขาแต่ละคนสามารถเข้าสู่ 'หน้า / พอร์ทัล' เฉพาะ (ประเภทโพสต์ที่กำหนดเอง) ของตัวเองโดยไม่สามารถเข้าถึง wp-admin เป็นต้น (ฉันสร้างทั้งหมด หน้าเข้าสู่ระบบ / ลงทะเบียน / แก้ไขโปรไฟล์ในส่วนหน้า) ในหน้านี้ / พอร์ทัลทนายจะฝากข้อความและไฟล์สำหรับลูกค้าที่จะดาวน์โหลดตอนนี้ในทางทฤษฎีพูดลูกค้าคนหนึ่งสามารถเดา (หรือถ้ามีความรู้เกี่ยวกับไฟล์ของลูกค้าอื่น) ชื่อไฟล์อื่น ๆ และดาวน์โหลดแล้วสร้างปัญหากับความเป็นส่วนตัว / ความปลอดภัย / วัสดุที่เป็นความลับ ฯลฯ

ฉันกำลังมองหาไอเดีย / แนวคิดสำหรับวิธีแก้ปัญหาความคิดเริ่มต้นของฉันคือต้องมีลิงค์ดาวน์โหลดชี้ไปที่ download.php บางอย่างที่ส่งรหัสสิ่งที่แนบ, รหัสผู้ใช้, หน้า / พอร์ทัล ID และไม่ใช่และการประมวลผลขั้นสุดท้าย .

คุณคิดอย่างไร? ฉันอยู่ในเส้นทางที่ถูกต้องหรือวิธีการนี้ไม่สมบูรณ์หรือไม่

ขอบคุณ!


คุณพบวิธีแก้ปัญหาสำหรับเรื่องนี้หรือไม่?
brasofilo

@brasofilo, no ..
Amit

คำตอบ:


6

สิ่งที่ต้องเกิดขึ้นคือคุณต้องทำการร้องขอการดาวน์โหลดพร็อกซีสำหรับไฟล์ประเภทที่คุณต้องการผ่าน WordPress สมมติว่าคุณกำลังจะ จำกัด การเข้าถึงไฟล์ ".doc"

1. กำหนดตัวแปรเคียวรีที่ระบุไฟล์ที่ร้องขอ

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

2. อัปเดต. htaccess เพื่อส่งต่อคำขอสำหรับไฟล์ที่ถูก จำกัด ไปยัง WordPress

สิ่งนี้จะรวบรวมคำขอไปยังไฟล์ที่คุณต้องการ จำกัด และส่งกลับไปยัง WordPress โดยใช้ตัวแปรแบบสอบถามแบบกำหนดเองด้านบน แทรกกฎต่อไปนี้ก่อนRewriteCondบรรทัด

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

3. จับชื่อไฟล์ที่ต้องการในตัวแปรเคียวรีที่กำหนดเอง; และยืนยันการเข้าถึงไฟล์:

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วิธีนี้ใช้ได้กับการติดตั้งในไซต์เดียวเท่านั้น ! เพราะนี่คือ WordPress MU wp-includes/ms-files.phpแล้วอัปโหลดไปข้างหน้าการร้องขอแฟ้มในเว็บไซต์ย่อยผ่าน มีวิธีแก้ปัญหาสำหรับ WordPress MU เช่นกัน แต่มันก็มีส่วนเกี่ยวข้องมากกว่านี้


1
สวัสดีฉันไม่เห็นว่าคุณขอเกี่ยวกับฟังก์ชั่นนี้ในขั้นตอนintercept_file_requestที่เรียกว่าทุกที่ฟังก์ชั่นที่ถูกไล่ออก?
Bobz

จุดที่ดีมันควรจะติดอยู่wpฉันได้อัปเดตตัวอย่างแล้ว
Bendoh

3

ฉันเพิ่งมีปัญหาที่เกี่ยวข้องและเขียนบทความเกี่ยวกับเรื่องนี้

ฉันจะสมมติว่าการดาวน์โหลดถูกอัพโหลดผ่านการจัดการสื่อของ WordPress - หรือคุณมี ID ไฟล์แนบสำหรับการดาวน์โหลด

เค้าร่างของการแก้ปัญหา

  • ทำให้ภาพที่ส่งไดเรกทอรี 'ความปลอดภัย' (ในความรู้สึกนี้ฉันเพียงแค่ใช้ค่าเฉลี่ย.htaccessเพื่อป้องกันความพยายามใด ๆ ที่จะเข้าถึงโดยตรงของไฟล์ในไดเรกทอรีการอัปโหลด (หรือไดเรกทอรีย่อยดังกล่าว) - เช่นผ่านทางmysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)
  • สร้างลิงค์ดาวน์โหลดรวมถึง ID ไฟล์แนบ - ผ่านขั้นตอน WordPress เพื่อตรวจสอบสิทธิ์ของผู้ใช้ในการดูไฟล์แนบที่อนุญาต / ปฏิเสธการเข้าถึง

คำเตือน

  • นี้จะทำให้การใช้.htaccessเพื่อให้การรักษาความปลอดภัย หากไม่สามารถใช้งานได้ / เปิดใช้งาน (เช่นเซิร์ฟเวอร์ nginx) คุณจะไม่ได้รับความปลอดภัยมากนัก คุณสามารถป้องกันไม่ให้ผู้ใช้เรียกดูไดเรกทอรี uplods แต่การเข้าถึงโดยตรงจะทำงาน
  • ตามข้างต้น นี้ไม่ควรนำมาใช้ในการกระจายถ้าคุณต้องการความปลอดภัยแน่นอน เป็นเรื่องปกติถ้าการตั้งค่าเฉพาะของคุณใช้งานได้ - แต่โดยทั่วไปไม่สามารถรับประกันได้ บทความที่เชื่อมโยงของฉันเป็นส่วนหนึ่งพยายามที่จะแก้ไขปัญหานี้
  • คุณจะหลวมรูปขนาดย่อ การปิดกั้นการเข้าถึงโฟลเดอร์หรือโฟลเดอร์ย่อยโดยตรงจะหมายถึงไม่สามารถดูภาพขนาดย่อของไฟล์ในโฟลเดอร์นั้นได้ บทความที่เชื่อมโยงของฉันเป็นส่วนหนึ่งที่พยายามแก้ไขปัญหานี้

การปิดกั้นการเข้าถึงโดยตรง

ในการทำเช่นนี้ในโฟลเดอร์อัพโหลดของคุณ (หรือโฟลเดอร์ย่อย - เนื้อหาลับทั้งหมดจะต้องอยู่ในระดับความลึกไม่ว่าภายในโฟลเดอร์นี้) วาง.htaccessไฟล์ด้วยสิ่งต่อไปนี้:

Order Deny,Allow
Deny from all

ในเรื่องต่อไปนี้ฉันสมมติว่าคุณจะแนบเนื้อหาที่เป็นความลับเพื่อโพสต์ 'ลูกค้า' ประเภท สื่อใด ๆ ที่อัพโหลดบนหน้าแก้ไขลูกค้าจะถูกเก็บไว้ในuploads/conf/โฟลเดอร์

ฟังก์ชั่นเพื่อตั้งค่าไดเรกทอรีอัพโหลดที่ได้รับการป้องกัน

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

อัปโหลดเนื้อหาที่เป็นความลับ

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

    }

เมื่อทำเช่นนั้นแล้วเนื้อหาที่อัปโหลดควรอยู่ข้างในuploads/confและพยายามเข้าถึงโดยตรงโดยใช้เบราว์เซอร์ของคุณไม่ควรทำงาน

กำลังดาวน์โหลดเนื้อหา

มันง่ายมาก URL การดาวน์โหลดอาจเป็นบางสิ่งwww.site.com?wpse26342download=5(โดยที่ 5 คือรหัสสิ่งที่แนบมาของเนื้อหาที่อัปโหลด) เราใช้สิ่งนี้เพื่อระบุสิ่งที่แนบมาตรวจสอบการอนุญาตของผู้ใช้ปัจจุบันและอนุญาตให้ดาวน์โหลด

ก่อนอื่นให้ตั้งค่าตัวแปรคิวรี

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

ตอนนี้ตั้งค่าผู้ฟังให้ (อาจ) ทริกเกอร์การดาวน์โหลด ...

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

ความคิดเห็นสุดท้าย

รหัสข้างต้นอาจมีข้อผิดพลาดข้อบกพร่อง / ไวยากรณ์และไม่ได้ทดสอบและคุณใช้ความเสี่ยงของคุณเอง :)

URL การดาวน์โหลดสามารถ 'prettified' โดยใช้การเขียนซ้ำ ตามที่ระบุไว้ในความคิดเห็นที่คุณสามารถเพิ่มว่างเปล่าindex.phpภายในลูกของโฟลเดอร์ที่มีการป้องกันทุกคนที่จะป้องกันไม่ให้เกิดการเรียกดู - แต่นี้ควรได้รับการป้องกันโดย.htaccessกฎระเบียบอยู่แล้ว

วิธีที่ปลอดภัยกว่านั้นก็คือการจัดเก็บไฟล์สาธารณะนอกไดเรกทอรีสาธารณะ หรือในบริการภายนอกเช่น Amazon S3 สำหรับหลังคุณจะต้องสร้าง URL ที่ถูกต้องเพื่อดึงไฟล์จาก Amazon (ใช้รหัสส่วนตัวของคุณ) ทั้งสองสิ่งนี้ต้องการความเชื่อถือในระดับหนึ่งในบริการโฮสต์ / บุคคลที่สามของคุณ

ฉันจะระมัดระวังเกี่ยวกับการใช้ปลั๊กอินใด ๆ ที่แนะนำให้พวกเขาเสนอ 'ดาวน์โหลดที่ได้รับการป้องกัน' ฉันไม่พบสิ่งใดที่ให้ความปลอดภัยที่ดีพอ โปรดอย่าข้อเตือนใจของการแก้ปัญหานี้ด้วย - และฉันยินดีรับข้อเสนอแนะหรือคำวิจารณ์


1

อาจเป็นไปได้ว่าคุณอาจรู้จักเคล็ดลับนี้รหัสนี้จะตรวจสอบชื่อผู้ใช้ที่เข้าสู่ระบบในปัจจุบันและถ้ามันตรงกับมันจะแสดงลิงค์ดาวน์โหลดไปยังไฟล์นั้นมิฉะนั้นมันจะไม่แสดงอะไรเลย

นี่คือรหัส:

<?php 
    global $current_user;
    get_currentuserinfo();

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

อย่างไรก็ตามนี่จะไม่ใช่วิธีการที่ดีเนื่องจากไฟล์จะถูกเก็บไว้ในเซิร์ฟเวอร์ทุกคนที่มีลิงก์สามารถดาวน์โหลดไฟล์นั้นได้


0

ฉันเข้าใจว่าข้อมูลนี้เป็นความลับและดังนั้นนอกเหนือจากการซ่อนลิงก์ไปยังไฟล์ที่คุณต้องการทำให้พวกเขาไม่สามารถเข้าถึงได้อย่างสมบูรณ์กับทุกคนบนเว็บแม้ว่าพวกเขาจะคาดเดา URL เว้นแต่ผู้ใช้นั้นจะได้รับอนุญาตอย่างชัดเจนให้ดาวน์โหลด ไฟล์

ดูการจัดเก็บไฟล์บนAmazon S3อย่างปลอดภัยจากนั้นให้URL ที่ลงนามล่วงหน้า (จำกัด เวลา) ไปยังไฟล์หากการตรวจสอบความปลอดภัยที่ถูกต้องได้รับการตอบสนอง (เช่นผู้ใช้เข้าสู่เว็บไซต์ของคุณและพวกเขาเป็นใคร)

มีAWS SDKที่ดีมากที่ทำให้ส่งตรงไปตรงมาได้

สิ่งที่คุณจะต้องวิจัยเป็นวิธีการในการส่งไฟล์ที่อัปโหลดผ่านอินเตอร์เฟซ WP อัปโหลดลงใน S3 แทนผลัดกันสร้างของคุณเองอัปโหลด

ตัวเลือกอีกก็จะเกินไปมองเข้าไปในรหัสของWP E-commerce มีการดาวน์โหลดไฟล์ซอฟต์แวร์ที่ปลอดภัย (เช่น MP3) ฉันเชื่อว่าไฟล์จะถูกแปลงเป็นแฮชด้วยคีย์เข้ารหัสที่สร้างต่อผู้ใช้เมื่อซื้อ อาจต้องใช้การถอดรหัสเพื่อดูว่ามันทำงานอย่างไร แต่กระบวนการจะไม่ซ้ำกับปลั๊กอินนี้ดังนั้นตัวอย่างอื่น ๆ จะพร้อมใช้งาน (บางแห่ง)


0

ฉันคิดว่าการเข้ารหัสไฟล์เป็นวิธีที่จะไปเหมือนคำตอบข้างต้น มีปลั๊กอินใน Wordpress.org ที่ให้คุณป้องกันการดาวน์โหลด http://wordpress.org/extend/plugins/download-protect/ คุณสามารถใช้บริการ amazons หรือ google ไดรฟ์ได้เช่นกัน มีบริการมากมายที่เสนอการดาวน์โหลดที่ได้รับการปกป้องเช่นกล่องดร็อปเกินไป


การรักษาความปลอดภัยผ่านความสับสนเป็นวิธีที่ไม่ดี ทุกคนจะสามารถเห็นคำขอ http และรับ URL ด้วยวิธีนี้
mulllhausen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.