Php 如何根据文件扩展名验证文件类型?

Php 如何根据文件扩展名验证文件类型?,php,mime-types,mime,file-type,Php,Mime Types,Mime,File Type,我想创建一个上载脚本,并定义一些允许上载的文件类型,以通过重命名文件扩展名来防止欺骗我使用此数组: 首先,它检查是否允许文件扩展名(例如xsl),然后使用finfo获取mimtype以检查该数组,查看mimtype是否与扩展名匹配 我上传了一个.xsl文件,finfo retruns文件类型为application/octet stream,但xsl扩展名的数组返回application/x-msexcel,因此它将不相等,也不会被验证 我是否应该忘记mimetype与脚本的文件扩展名验证器匹配

我想创建一个上载脚本,并定义一些允许上载的文件类型,以通过重命名文件扩展名来防止欺骗我使用此数组: 首先,它检查是否允许文件扩展名(例如xsl),然后使用finfo获取mimtype以检查该数组,查看mimtype是否与扩展名匹配

我上传了一个.xsl文件,finfo retruns文件类型为application/octet stream,但xsl扩展名的数组返回application/x-msexcel,因此它将不相等,也不会被验证


我是否应该忘记mimetype与脚本的文件扩展名验证器匹配,而只检查文件扩展名?或者我该怎么办?

基本上你做对了。千万不要依赖上传表单发送的mime类型头,因为你可以很容易地伪造它,或者它不存在,那么你通常会得到
应用程序/octet流

因此,这是检查文件扩展名是否与此文件扩展名允许的mime类型匹配的好方法

我看到你把这个名单连起来了。这当然是一个很好的列表,但对于php来说并不实用,因为数组中的ovverriden太多了,例如:

$mimeTypes = array(
    'xlm' => 'application/vnd.ms-excel',//overridden
    'xlm' => 'application/x-excel',
    'xls' => 'application/excel',//overridden
    'xls' => 'application/vnd.ms-excel'
);

var_dump( $mimeTypes );
这将只输出两个值而不是四个值,您应该使用如下数组:

$mimeTypes = array(
    'xlm' => array( 'application/vnd.ms-excel', 'application/x-excel' ),
    'xls' => array( 'application/excel', 'application/vnd.ms-excel' ),
    'txt' => array( 'text/plain' )
);

var_dump( $mimeTypes );
因此,如果您已经有了文件扩展名,只需使用检查mimetype即可

这是一个基本的例子,你可以解决它注意:这不是一个有效的例子,但我想你知道我想指出的地方:

// you have your file, you said it´s excel but you uploaded it with extension txt
$filepath = "excel.txt";

if( strpos( $filepath, '.' ) === false ) {
    // no file extension
    // return ?
}
// get the file extension
// well there is surely a better way
$filenameParts = explode( ".", $filepath );
$fileExt = array_pop( $filenameParts );// return the las element of the array and REMOVES it from the array

// your fopen stuff to get the mime type
// ok let´s say we are getting back the follwing mime type
$fileMimeType = 'application/vnd.ms-excel';

// now check if filextension is in array and if mimetype for this extension is correct
if( isset( $mimeTypes[$fileExt] ) && in_array( $fileMimeType, $mimeTypes[$fileExt] ) ) {
    // file extension is OK AND mime type matches the file extension
} else {
    // not passed unknown file type, unknown mime type, or someone tricked you
    // your excel.txt should end up here
}

您是如何确保文件类型为“应用程序/八位字节流”的,如果您在文件数组中这样做,那么它是不可靠的,很容易伪造。如果无法识别,则发送文件类型头“应用程序/八位字节流”。这并不总是意味着上传的文件属于这种类型。您应该检查上传的文件,而不是从finfo::buffer返回的mime typesoctet流的$\u FILES数组。然后我从数组中得到了xsl扩展的mimetype,它是x-msexel,所以它们并不相等。如何根据扩展名验证文件mimetype以避免重命名技巧?只允许提供扩展列表,以便有人可以重命名和上载它。如何验证?我想你给了我线索。我使用的是finfo::buffer,因此不可靠,我将其更改为使用物理文件打开的文件,现在它返回application/vnd.ms-excel,而不是预期的八位字节流。但现在另一个问题是:当我将文件名重命名为.txt以欺骗上传时,如何验证这是否是允许的文件?我是否应该使用array_exists来传递该类型以获取数组键as.xsl,以查看这是不允许的?我认为,这就是验证的要点。如果mime类型是application/vnd.ms-excel,那么它必须是一个具有excel扩展名的文件,否则您的mime类型检查只能是“半”安全的:)我创建了这个数组pastebin.com/d4ZQBe5A,或者通过加入以下所有列表+.php扩展名,所有列表中都缺少该扩展名。请对此列表作出贡献,使其尽可能准确和完整。总计:截至2015年11月16日,共有1223个扩展名。没有扩展名的文件如何?如何允许上传?对于文件大小,在$u文件上使用mb_strlen可靠吗?或者只应使用物理文件上的文件大小?某些扩展名,如.docs.docx.xlsm。。。。。没有列在那里。你能帮我添加它们吗?我通过加入下面所有的列表+.php扩展名创建了这个数组,它们都缺少这个扩展名。请对此列表作出贡献,使其尽可能准确和完整。总计:截至2015年11月16日,共有1223个扩展名。我已更新了答案并添加了一个条件:
strpos($filepath,”)===false
,在这里您可以返回false或其他内容,如果没有文件扩展名,这也可以避免,如果文件本身名为“xls”,因为文件大小我无法给您一个好的建议,因为在此上下文中我对文件大小的安全性一无所知,所以我总是使用$\u FILES数组中的文件大小,没有问题