PHP生成的JSON文件具有application/octet-stream mime类型

VeZ*_*oul 5 php json mime-types

我有一个脚本,可以从数据生成JSON文件.我有第二个脚本,从目录中读取文件只接受JSON文件并将其插入数据库.

问题是第二个脚本从我生成的文件中检测"application/octet-stream"MIME类型而不是 application/json

我不想允许application/octet-streamMIME类型,因为它可以是任何东西(出于安全原因:第二个脚本加载json目录中的所有文件(不仅是生成的文件)).

那么无论如何都要"设置"文件的MIME类型?

生成文件的代码:

if($r_handle = fopen($s_file_name, 'w+')){
    fwrite($r_handle, json_encode($o_datas, JSON_HEX_QUOT | JSON_HEX_TAG));
    fclose($r_handle);
    return;
}
Run Code Online (Sandbox Code Playgroud)

读取JSON文件的代码:

$o_finfo = finfo_open(FILEINFO_MIME_TYPE);
$a_mimes =& get_mimes();
if(is_dir($s_dir) && $r_handle = opendir($s_dir)){
    while($s_file = readdir($r_handle)){
        $s_file_path = $s_dir.$s_file;
        $s_mime      = finfo_file($o_finfo, $s_file_path);
        if(!in_array($s_file, array('.', '..')) && in_array($s_mime, $a_mimes['json'])){
            // Some code
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Álv*_*lez 1

fileinfo扩展(与file Unix 命令类似的工具)基本上搜索数据库中定义的签名(称为“magic”)。如果我没记错的话,PHP 的魔法数据库当前已编译到扩展二进制文件中,因此您无法查看它,但您的系统中可能会有一个类似的数据库。我有 Apache 的 at C:\Apache24\conf.magic,这是 JPEG 的条目:

# JPEG images
0   beshort     0xffd8      image/jpeg
Run Code Online (Sandbox Code Playgroud)

任何开头的0xffd8都是图片。完毕!

十六进制编辑器中的 JPEG 文件

我不是特别熟悉这种格式,但它似乎根本不寻找JSON。而且,正如您可能已经猜到的那样,整体实用程序绝不是安全功能。它只是一个帮助工具来确定文件可能包含的内容。例如,如果您从损坏的磁盘中恢复了没有扩展名的文件,这将非常方便。


MIME 类型很酷。你设置了application/json,每个人都知道它是 JSON。简单明了,不是吗?只有两个警告:

  • 文件系统(其中许多实际上是在 MIME 类型之前发明的)存储许多文件属性(名称、上次修改日期、权限,有时甚至是图标...),但不存储 MIME 类型。(当然,可能有一些学术文件系统可以做到这一点,但 FAT32、NTFS、ext4... 则不然)。它通常不会添加有价值的信息,它是另一个保持更新的令牌,并且特别不可移植(将文件复制到拇指驱动器,它们就会消失)。

  • 它仍然不是一个安全功能。如果我可以伪造文件内容,那么什么可以阻止我伪造 MIME 类型?


所以,你可以做什么?最好的选择是:什么都不做。

只需将文件解析为 JSON 并检测是否失败。无论如何你都需要这样做,它会告诉你需要做的一切。JSON 只是纯文本数据。也许添加一些检查以防止非常大的文件(同样,您应该在文件上传中执行此操作)并添加检查,$depth但仅此而已。

if (json_decode($s_file_path, true, 32)!==null || json_last_error()!==JSON_ERROR_NONE) {
    // Valid JSON
}
Run Code Online (Sandbox Code Playgroud)