下载滥用 php Content-Disposition:附件和读取文件

Download abuse with php Content-Disposition: attachment and readfile

我遇到了 php Content-Disposition: attachment 和 readfile 的下载滥用问题。看来我的问题出在 readfile 上,因为虽然这个脚本有效,但无论客户端是否关闭浏览器,readfile 都会读取 mp4 的全部内容,从而设置滥用脚本启动下载并立即关闭进程的可能性。某个地方的东西是 运行 一个脚本,它每秒点击这个 link 数百次,运行 我的 php 脚本并立即取消他们的下载,但我的服务器正在准备每次卸载整个文件。

这是我 运行 的脚本,当 user/abuser 点击下载时 link:

<?php
// get MP4 address
$MP4Address = $_GET["MP4Address"];

// We'll be outputting a MOV
header( 'Content-Type: application/octet-stream' );

$filename = basename($MP4Address);

// Name file
header('Content-Disposition: attachment; filename="'.$filename.'"');

// Source file
readfile($MP4Address);
?>

我怀疑 readfile 是罪魁祸首,但如果没有它,客户端将收到一个空文件。必须有一种更现代、更正确的方法来做到这一点,但我不确定它可能是什么。

除非您调用了 ignore_user_abort(true) PHP 应该会收到连接已中止并停止执行的信号。但是一旦你进入 readfile() 调用 PHP 就可能无法监视该信号,因为它正忙于执行 low-level IO.

我会说您有 2 个选择,第一个是简单地编写一些代码来检测和阻止滥用您服务的人。您的下载已经由 PHP 脚本支持,因此添加一些检查和过滤应该相对简单。

另一种方法是将 readfile() 调用替换为一些 [公认效率较低] 的代码,这些代码应该会给 PHP 一些呼吸 space 来寻找用户中止。

function read_file($filename, $chunksize=4096) {
  if( ! $fh = fopen($filename, 'rb') ) {
    throw new \Exception('Failed to open file');
  }
  while($chunk = fread($fh, $chunksize)) {
    echo $chunk;
  }
  fclose($fh);
}