如何将附件下载限制为特定用户?

时间:2011-08-19 作者:Amit

我有一个非常具体的用例,为律师和他的每个客户构建的网站都可以登录到他们自己的“特定页面/门户”(自定义帖子类型),而无需访问wp admin等(我在前端创建了所有登录/注册/档案编辑页面)。在此页面/门户中,律师将留言和files for the client to download, 从理论上讲,一个客户可以猜测(或者如果知道另一个客户的文件)其他文件名并下载,从而产生隐私/安全/机密材料等问题。

我正在寻找解决方案的想法/概念,我最初的想法是让下载链接指向一些下载。php发送附件id、用户id、页面/门户id和nonce,并在另一端处理。。

你觉得怎么样?我的思路是否正确,或者这种方法是否有缺陷?

谢谢

5 个回复
最合适的回答,由SO网友:Bendoh 整理而成

需要做的是,您需要通过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 此解决方案适用于单站点安装only! 这是因为WordPress MU已经通过wp-includes/ms-files.php. WordPress MU也有一个解决方案,但它更复杂一些。

SO网友:Stephen Harris

我最近遇到了一个相关的问题wrote this article about it.

我假设下载是通过WordPress的媒体处理上传的,或者你有下载的附件ID。

解决方案概要使上传目录“安全”(从这个意义上说,我只是想使用.htaccess 阻止直接访问上载目录(或其子目录)中文件的任何尝试-例如,通过mysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf)

    注意事项This makes use of .htaccess to provide security. 如果这不可用/未打开(例如,nginx服务器),那么您将不会获得太多安全性。您可以阻止用户浏览uplods目录。但直接访问将起作用如上所述。This should not be used in distribution if you require absolute security. 如果您的特定设置起作用,这是很好的-但一般来说,它不能保证。我的链接文章部分是为了解决这个问题
  • You will loose thumbnails. 阻止直接访问文件夹或子文件夹将意味着无法查看该文件夹中文件的缩略图。我的链接文章部分是为了解决这个问题
    • 要在上载文件夹(或子文件夹-所有机密材料必须位于此文件夹的任何深度)中执行此操作,请阻止直接访问。放置a.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获取文件(使用您的私钥)。这两者都需要对主机/第三方服务具有一定程度的信任。

      我会小心使用任何建议他们提供“受保护下载”的插件。我还没有找到足够安全的。请不要对这个解决方案提出警告,我欢迎任何建议或批评。

SO网友:amit

您可能已经知道这个技巧,这段代码将检查当前登录用户的用户名,如果匹配,它将显示该文件的下载链接,否则它不会显示任何内容。

here is the code :

<?php 
    global $current_user;
    get_currentuserinfo();

    if ( \'username\' == $current_user->user_login ) {
        echo \'Download Link\';
    } else {
        // nothing
    }
?>
然而,这不是一个好方法,因为文件存储在服务器上,任何有链接的人都可以下载该文件。

SO网友:deadlyhifi

我认为这些信息是机密信息,因此除了隐藏指向文件的链接之外,你还想让web上的任何人都无法访问这些链接,即使他们猜测URL,除非该用户有下载文件的明确权限。

研究将文件存储在Amazon S3 安全地,然后提供pre signed (有时间限制)如果满足正确的安全检查,则指向文件的URL(即用户已登录到您的网站,并且是他们所说的用户)。

有一个非常好的AWS SDK 这样做非常简单。

您需要研究的是如何将通过WP上载接口上载的文件发送到S3,或者构建自己的uploader.

另一种选择是深入研究WP e-commerce. 他们提供软件文件(如MP3)的安全下载。我相信这些文件会被转换成哈希,加密密钥是每个用户在购买时生成的。这将需要一些解密来了解它是如何工作的,但是这个过程对于这个插件来说并不是唯一的,所以其他的例子(在某处)也可以得到。

SO网友:Chris

我认为文件的加密就是上面的答案。Wordpress上有一个插件。org,让您保护下载。http://wordpress.org/extend/plugins/download-protect/你也可以使用亚马逊服务或谷歌硬盘。还有很多服务提供受保护的下载,比如drop box。

结束

相关推荐