从 mime 字节验证 base64 编码图像

Posted

技术标签:

【中文标题】从 mime 字节验证 base64 编码图像【英文标题】:Validate base64 encoded image from mime byte 【发布时间】:2018-04-01 03:39:06 【问题描述】:

我正在尝试从 mime 类型字节验证一些 Base64 编码的图像,除了 .png 文件之外,它们都在正确验证

png字节签名为89 50 4E 47 0D 0A 1A 0A

我有一个允许的字节签名数组

    'imageBytes'    => [
        "jpeg"  => "FFD8",
        "png"   => "89504E470D0A1A0A",
        "gif"   => "474946",
        "bmp"   => "424D"
    ],

我使用允许的数组将 base64 编码图像传递给此函数

    public function checkImageMimeBytes(string $imageData, array $imgByteArray) : string
        
            if (!is_array($imgByteArray) || is_null($imgByteArray) || empty($imgByteArray)) 
                throw new \LogicException('undefined image security config');
            

            foreach ($imgByteArray as $mime => $hexBytes) 
                $bytes = $this->getBytesFromHexString($hexBytes);
                if (substr($imageData, 0, strlen($bytes)) == $bytes) 
                    return $mime;
                 else 
                    throw new SecurityException;
                
            
            throw new \LogicException('Invalid Mime Byte');
        

这个函数从十六进制字符串中获取字节

        public function getBytesFromHexString(string $hexData) : string
        

            for ($count = 0; $count < strlen($hexData); $count += 2) 
                $bytes[] = chr(hexdec(substr($hexData, $count, 2)));
            

            if (!isset($bytes) || !is_array($bytes) || empty($bytes) || is_null($bytes)) 
                throw new \LogicException;
            

            return implode($bytes);
        

在测试时,它总是会为 .png 图像引发安全异常

关于如何解决这个问题的任何信息?

添加了测试图片

编辑: 使用 FileReader() 从 javascript 编码前端

     let reader = new FileReader()
     reader.readAsDataURL(file)
        reader.onloadend = (readEvent) => 
          this.$emit('imageUploadReady', readEvent.currentTarget.result)
        

【问题讨论】:

我们不知道您的数据是什么样的。 你试过使用base64_encode和base64_decode吗? 为什么我需要对其进行编码和解码?我用javascript对其客户端进行编码并在服务器端对其进行解码? 添加了测试图片 图像没有帮助。显示数据。 【参考方案1】:

简介

和你一样,我有一个 base64 图像 ($imageBase64Str)。

我需要获取这张图片的 mime 类型,它必须是有效的。

回答

输入:$imageBase64Str

function imgMime($imgBytes)
    if(is_null($imgBytes))
        return(false);
    
    if(strlen($imgBytes)<12)
        return(false);
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime=$finfo->buffer($imgBytes);
    if(strncmp($mime, "image/", 6) != 0)
        return(false);
    
    return($mime);


$imageBytes=base64_decode($imageBase64Str,true);
if(!$imageBytes)
    throw new Exception("cannot decode image base64");

$imageMime=imgMime($imageBytes);
if(!$imageMime)
    throw new Exception("cannot recognize image mime");

如果您希望将图像类型限制为比exif_imagetype 函数识别的更窄的一组MIME,您可以根据image_type_to_mime_type 函数返回的$imageMime 引发错误。像这样的:

$allowedMimes=["image/jpeg","image/png","image/gif","image/bmp"];
if(!in_array($imageMime,$allowedMimes,true))
    throw new Exception("image mime not allowed: ".$imageMime);

结果

当我将$imageBase64Str 设置为从your example 提取的iVBORw0KGgoAAAANSUhEUgAAAQwAAABuCAYAAADSxy12AAAgAElEQVR4XtV9267jSpJd8CaSukvVv+LpA...Vxt5tFRObQnEEvPk4fVOUFg5tz2709kx8kLz9c0yWJqDQQqfvvSxPV0wVSYRMAAAAASUVORK5CYII= 时,我得到了一个有效的image/png mime。但是,我没有得到酷炫的黑白匿名奴才牛仔图像,而是下面的紫色/紫色旋转方块:

【讨论】:

以上是关于从 mime 字节验证 base64 编码图像的主要内容,如果未能解决你的问题,请参考以下文章

PHP:来自图像字节的图像 mime 类型

从 Base64 编码的字符串中检索 MIME 类型

在python中将base64编码的图像解码为原始图像

如何将图像的字节数组转换为表示 jpg 的 base64 编码字符串

将base64字符串编码的图像/字节图像作为图像在Flutter中用于Firebase ML Vision中进行处理

将 Base64 编码的图像写入文件