특정 사용자에게 첨부 파일 다운로드를 제한하는 방법은 무엇입니까?


12

변호사를 위해 만들어진 사이트와 각 고객이 wp-admin 등에 액세스하지 않고도 자신의 '특정 페이지 / 포털'(사용자 정의 게시물 유형)에 로그인 할 수있는 매우 구체적인 사용 사례가 있습니다. 프론트 엔드의 로그인 / 등록 / 프로필 편집 페이지). 이 페이지 / 포털에서 변호사는 클라이언트가 다운로드 할 메시지와 파일을 남겨두고 이론적으로 말하자면 한 클라이언트는 다른 파일 이름을 추측 (또는 다른 클라이언트의 파일에 대한 지식이있는 경우)하고 파일을 다운로드 한 다음 개인 정보 보호 / 보안 문제를 일으킬 수 있습니다. / 기밀 자료 등

솔루션에 대한 아이디어 / 개념을 찾고 있는데, 처음에는 다운로드 링크가 일부 download.php로 연결되어 첨부 파일 ID, 사용자 ID, 페이지 / 포털 ID 및 nonce를 보내고 다른 쪽 끝을 처리하는 것이 었습니다. .

어떻게 생각해? 내가 올바른 길을 가고 있거나이 접근법에 결함이 있습니까?

감사!


이에 대한 해결책을 찾았습니까?
brasofilo 2016 년

@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. 제한된 파일에 대한 요청을 WordPress에 전달하도록 .htaccess를 업데이트하십시오.

그러면 제한하려는 파일에 대한 요청을 캡처하고 위의 사용자 정의 쿼리 변수를 사용하여 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. 예를 업데이트했습니다.
벤도

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는 업로드 된 컨텐츠의 첨부 파일 ID입니다). 이를 사용하여 첨부 파일을 식별하고 현재 사용자의 권한을 확인한 후 다운로드 할 수 있습니다.

먼저 쿼리 변수를 설정하십시오.

/**
 * 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을 '미리 확인'할 수 있습니다. 주석에 명시된 바와 같이 index.php탐색을 방지하기 위해 보호 된 폴더의 모든 자식 안에 공백을 추가 할 수 있지만 .htaccess어쨌든 규칙에 의해 방지해야 합니다.

보다 안전한 방법은 공용 파일을 공용 디렉토리 외부에 저장하는 것입니다. 또는 Amazon S3와 같은 외부 서비스에서. 후자의 경우 유효한 개인 URL을 사용하여 Amazon에서 파일을 가져 오려면 유효한 URL을 생성해야합니다. 이 두 가지 모두 호스트 / 타사 서비스에 대한 특정 수준의 신뢰가 필요합니다.

'보호 된 다운로드'를 제공하는 플러그인을 사용하는 것에 대해 조심할 것입니다. 충분한 보안을 제공하는 제품을 찾지 못했습니다. 이 솔루션의주의 사항도주의하지 마십시오. 제안이나 비판을 환영합니다.


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 전자 상거래 코드를 살펴 보는 것 입니다. 소프트웨어 파일 (예 : MP3)의 안전한 다운로드를 제공합니다. 나는 구매시 사용자마다 생성되는 암호화 키를 사용하여 파일이 해시로 변환된다고 생각합니다. 작동 방식을 확인하려면 약간의 해독이 필요하지만 프로세스는이 플러그인에만 고유하지 않으므로 다른 예제 (어딘가)를 사용할 수 있습니다.


0

파일 암호화가 위의 답변과 같은 방법이라고 생각합니다. Wordpress.org에는 다운로드를 보호 할 수있는 플러그인이 있습니다. http://wordpress.org/extend/plugins/download-protect/ Amazon 서비스 또는 Google 드라이브를 사용할 수도 있습니다. 드롭 박스와 같은 보호 된 다운로드를 제공하는 많은 서비스가 있습니다.


모호성을 통한 보안은 나쁜 접근 방식입니다. 누구나 http 요청을 보고이 방법으로 URL을 얻을 수 있습니다.
mulllhausen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.