PHP:如何阻止直接访问文件的URL,但仍允许已登录用户下载?

39

我有一个网站,用户应该能够登录并播放歌曲(自制的mp3)。我想让已登录的用户可以听取/下载/执行其他操作,并且文件应该驻留在服务器上(不存储在MySQL数据库中),但不能被具有URL路径的非用户访问。

例如:假设我的mp3位于mysite.com/members/song.mp3,如果您已登录,您应该能够看到mysite.com/members/index.php页面,该页面将允许访问song.mp3文件。如果未登录,则mysite.com/members/index.php页面将不会显示song.mp3文件,直接链接也无法获得访问权限。

我相当确定这可以通过htaccess完成,并且我已经进行了大量的谷歌搜索,并在这里搜索过。我找到的两个最接近的答案是这个htaccess指南:http://perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/和这个StackOverflow问题:Block direct access to a file over http but allow php script access,但都没有回答完全符合我的要求。我还遗漏了什么?

3个回答

61

在文件夹 members 中创建新文件夹 files,将所有歌曲移动到此处,创建新的 .htaccess 文件并添加以下内容:

Order Deny,Allow
Deny from all


members文件夹中创建get_song.php文件,并添加以下代码:

if( !empty( $_GET['name'] ) )
{
  // check if user is logged    
  if( is_logged() )
  {
    $song_name = preg_replace( '#[^-\w]#', '', $_GET['name'] );
    $song_file = "{$_SERVER['DOCUMENT_ROOT']}/members/files/{$song_name}.mp3";
    if( file_exists( $song_file ) )
    {
      header( 'Cache-Control: public' );
      header( 'Content-Description: File Transfer' );
      header( "Content-Disposition: attachment; filename={$song_file}" );
      header( 'Content-Type: application/mp3' );
      header( 'Content-Transfer-Encoding: binary' );
      readfile( $song_file );
      exit;
    }
  }
}
die( "ERROR: invalid song or you don't have permissions to download it." );

现在,您可以使用以下URL获取歌曲文件:
http://mysite.com/members/get_song.php?name=my-song-name

4
可以将文件存储在wwwroot之外,而不是拒绝直接访问。 - Salman A
我尝试从文件夹中读取文本文件,这个方法可行,但是我无法通过调用PHP来显示JPEG图像。我将Content-Type设置为image/jpeg。如果有人已经尝试过使用图像,请帮帮我。 - Avigit
我尝试了这个,但是在文件下载后无法打开它们:无法打开流:HTTP请求失败!HTTP/1.1 403 Forbidden - zylo

7

你只能通过 .htaccess 要求来自你的网站的 referer,但这不安全。伪造 referer 非常容易,任何人都可以把你的网站搞垮。

唯一的方法是将文件放在网站根目录之外,并使用 PHP 脚本控制访问权限,只允许已登录用户下载。简而言之:

if (is_logged_in()) {
   readfile($name_of_file);
} else {
   die("Access denied");
}

7
不会说它是“唯一的事情”。 - Nick

3
如果您使用像PHP这样的脚本语言来处理网站,那么最好的方法是创建一个可以处理“内容交付”的脚本。将内容保存在受保护的目录中,即在您的http或www文件夹上方。然后,当用户登录时,指向您的内容的链接应该是这样的:http://yoursite.com/listen.php?song_id=xxx。脚本将根据ID查找所需的歌曲,然后向用户呈现数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接