如何在php保存之前拒绝文件上传?

时间:2014-01-17 00:31:54

标签: php file-upload

据我所知,PHP将文件保存到临时目录,之后我可以通过$ _FILES处理该文件。

我需要在PHP开始下载文件之前检查一些东西 - 如果会话有效,如果referrer有效...那么我可以防止未经授权的上传者将垃圾保存到php临时目录。

这是怎么做的?

我知道如何在perl中做得很好,但我正在寻找没有php.ini修改或.htaccess修改的纯PHP解决方案。

2 个答案:

答案 0 :(得分:2)

当您将Content-Type更改为PHP无法解析的内容时(例如'raw / data'),您可以从php://input读取所有POST数据,因此当脚本运行时您可以执行首先验证,如果您满意,则读取数据并将其保存到磁盘。

这是PHP代码

<?php 
    preg_match("/^(.*)\/([^\/]+)$/", $_SERVER['SCRIPT_NAME'], $SRVR);
    $SRVR=$_SERVER['HTTP_ORIGIN'].$SRVR[1];
    if (!strstr($_SERVER['HTTP_REFERER'], $SRVR)) {
        echo "Status: 418 I'm a teapot (RFC 2324)\n\n";
        exit;
    }

    session_name('MYSESSION');
    session_start();

    if (!$_SESSION['LoggedID']) {
        echo "Invalid Session";
        exit;
    }

    session_write_close(); // quite useful - 'unlock' the session variables

    $HEADERS=getallheaders();

    if (!$HEADERS['UPL_FileName']) {
        echo "Invalid FileName";
        exit;
    }
    if (!$HEADERS['UPL_TMP']) {
        $HEADERS['UPL_TMP']=rtrim(base64_encode(md5(microtime())),"=");
    }

    $in=fopen('php://input', 'r');
    $SIZE=0;
    $out=fopen('tmp/'.$HEADERS['UPL_TMP'], 'wb');
    while(!feof($in)){
        usleep(10000); // simulate slow upload - for testing progress status/bar
        fwrite($out, fgets($in, 2048));
    }

    fclose($out);
    fclose($in);

    rename('tmp/'.$HEADERS['UPL_TMP'], $HEADERS['UPL_FileName']);   

    echo "Upload OK [", $HEADERS['UPL_TMP'], "]";

?>

以及JavaScript代码

function getXMLHttp() {
    var ajax;
    if (window.XMLHttpRequest) {
        ajax=new XMLHttpRequest();
    } else {
        ajax=new ActiveXObject('Microsoft.XMLHTTP');
    }
    return ajax;
}

var ajax=getXMLHttp();
ajax.onreadystatechange = function () {
    if (this.readyState==4) {
        console.log(this.responseText);
    }
}
ajax.open('POST', 'upload.php', true);
ajax.setRequestHeader('Content-Type', 'raw/data');
ajax.setRequestHeader('UPL_FileName', 'tmp/test.jpg');
ajax.setRequestHeader('UPL_TMP', 'ABCDE');
ajax.send(document.getElementById('uploader').files[0]);

...期待文件标签的id ='uploader'

希望它会帮助某人; - )

答案 1 :(得分:0)

简答:以正常形式发布操作,没有。 PHP不能“要求更多”。通过PUT或POST作为multipart/form-data通过表单上传的文件离开客户端,进入您的Web服务器,并完全交给PHP处理到$_FILES

显然,在a host of other vulnerabilities中,拒绝服务攻击已经成熟。

Javascript,特别是使用the HTML5 File API,您可以在浏览器中访问文件数据。然后,您可以将所述文件数据的任何部分发送回PHP进行验证(使用XHR),然后在验证通过后继续上传。