web-dev-qa-db-ja.com

添付ファイルのダウンロードを特定のユーザーに制限する方法

私は、弁護士のために作られたサイトと彼のクライアントのそれぞれが、wp-adminなどにアクセスすることなく彼ら自身の '特定のページ/ポータル'(カスタム投稿タイプ)にログインできるという非常に特殊なユースケースを持っています。フロントエンドのログイン/登録/プロフィール編集ページ)このページ/ポータルでは、弁護士はメッセージとクライアントがダウンロードするファイルを残します。プライバシー/セキュリティ/機密資料などの問題.

私は解決策のアイデア/概念を探しています、私の最初の考えは、添付ファイルID、ユーザーID、ページ/ポータルID、およびnonceを送信するダウンロードリンクへのダウンロードを指すことです。 。

どう思いますか?私は正しい方向に進んでいるのか、それともこのアプローチに欠陥があるのか​​?

ありがとうございます。

12
Amit

何が起こる必要があるのはあなたが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にも解決策がありますが、もう少し複雑です。

5
Bendoh

私は最近、関連する問題に遭遇しました それについてこの記事を書きました

ダウンロードは、WordPressのメディア処理を介してアップロードされることを前提としています。そうでない場合は、ダウンロード用の添付ファイルIDを持っています。

ソリューションの概要

  • アップロードディレクトリを「セキュア」にする(この意味で、Ijustは、.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からファイルを取得する必要があります(秘密キーを使用)。これらは両方とも、ホスト/サードパーティサービスで一定レベルの信頼を必要とします。

私は、それらが「保護されたダウンロード」を提供することを示唆するプラグインの使用について警戒するでしょう。十分なセキュリティを提供するものを見つけていません。この解決策の警告もしないでください-提案や批判を歓迎します。

3
Stephen Harris

おそらく、あなたはこのトリックを知っているかもしれません。このコードは現在ログインしているユーザーのユーザー名をチェックし、それが一致すればそのファイルへのダウンロードリンクを表示し、そうでなければ何も表示しません。

これがコードです:

<?php 
    global $current_user;
    get_currentuserinfo();

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

ただし、ファイルはサーバーに保存されているため、リンクを持つ人は誰でもそのファイルをダウンロードできますので、これは適切な方法ではありません。

1
amit

私は、ファイルの暗号化が上記の答えのようになる方法だと思います。 Wordpress.orgにはダウンロードを保護するためのプラグインがあります。 http://wordpress.org/extend/plugins/download-protect/ amazonサービスまたはGoogleドライブを使用することもできます。ドロップボックスなどの保護されたダウンロードを提供するサービスもたくさんあります。

0
Chris

私はこの情報は機密であると思います。そのため、ユーザーがダウンロードを明示的に許可していない限り、Web上の誰にも完全にアクセスできないファイルへのリンクを隠します。ファイル。

Amazon S3 に安全にファイルを保存してから、正しいセキュリティチェックが満たされている(つまり、ユーザーがログインしている)場合は、 事前署名済み (期限付き)URLをファイルに提供します。サイトであり、彼らが彼らであると言っている人です)。

AWS SDK という非常に優れたものがあり、これを実行するのは非常に簡単です。

調査する必要があるのは、WPアップロードインターフェイスを介してアップロードされたファイルをS3に送信する方法です。代わりに独自の uploader を作成します。

他の選択肢は、 WP e-commerce のコードを調べてもよいでしょう。彼らはソフトウェアファイル(例えば、MP3)の安全なダウンロードを提供する。購入時にユーザーごとに生成される暗号化キーでファイルがハッシュに変換されると思います。これがどのように機能するかを理解するにはある程度の解読が必要ですが、このプロセスはこのプラグインに固有のものではないので、他の例が利用可能になります(どこかで)。

0
deadlyhifi