在 laravel 中验证 base64 解码图像

Posted

技术标签:

【中文标题】在 laravel 中验证 base64 解码图像【英文标题】:Validate a base64 decoded image in laravel 【发布时间】:2016-12-26 19:58:56 【问题描述】:

我试图从 PUT 请求中获取图像以更新用户图片(使用邮递员),并使其通过 Laravel 5.2 中的验证,以便在邮递员中使用以下网址进行调用:

http://localhost:8000/api/v1/users?_method=PUT

并在正文中发送图像字符串,使用这样的 json:


    "picture" : "data:image/png;base64,this-is-the-base64-encode-string"

在控制器中尝试许多不同的方法来解码图像并尝试通过验证:

    首先我尝试了这个:

    $data = request->input('picture');
    $data = str_replace('data:image/png;base64,', '', $data);
    $data = str_replace(' ', '+', $data);
    $image = base64_decode($data);
    $file = app_path() . uniqid() . '.png';
    $success = file_put_contents($file, $image);
    

    然后我尝试了这个:

    list($type, $data) = explode(';', $data);
    list(, $data) = explode(',', $data);
    $data = base64_decode($data);
    $typeFile = explode(':', $type);
    $extension = explode('/', $typeFile[1]);
    $ext = $extension[1];
    Storage::put(public_path() . '/prueba.' . $ext, $data);
    $contents = Storage::get(base_path() . '/public/prueba.png');
    

    尝试使用干预图片库(http://image.intervention.io/),不要通过:

    $image = Image::make($data);
    $image->save(app_path() . 'test2.png');
    $image = Image::make(app_path() . 'test1.png');
    

这是控制器中的验证:

    $data = [
        'picture' => $image,
        'first_name' => $request->input('first_name'),
        'last_name' => $request->input('last_name')
    ];

    $validator = Validator::make($data, User::rulesForUpdate());
    if ($validator->fails()) 
        return $this->respondFailedParametersValidation('Parameters failed validation for a user picture');
     

这是用户模型中的验证:

public static function rulesForUpdate() 
    return [
        'first_name' => 'max:255',
        'last_name' => 'max:255',
        'picture' => 'image|max:5000|mimes:jpeg,png'
    ];
   

【问题讨论】:

我没有关注。您面临的问题是什么? 无法通过 base64 字符串创建的图像的验证 【参考方案1】:

你可以扩展 Laravel 的 Validator 类。

Laravel Doc

不过还是试试吧

Validator::extend('is_png',function($attribute, $value, $params, $validator) 
    $image = base64_decode($value);
    $f = finfo_open();
    $result = finfo_buffer($f, $image, FILEINFO_MIME_TYPE);
    return $result == 'image/png';
);

不要忘记规则:

$rules = array(
   'image' => 'is_png'
);

【讨论】:

如果黑客在输入中输入一个以“/9j”开头的字符串(例如:“/9jwhat_ever_additional_string_to_hack_here”),它仍然被检测为image/jpeg .... 所以此验证不安全 $result 变量返回“application/octet-stream”而不是“image/png”或“image/jpg”【参考方案2】:

如果您仍然使用干预,那么您可以将其用于自定义验证规则。我有一个叫做“可成像”的。它基本上确保给定的输入将能够转换为干预图像。 Base64 数据图像字符串将通过。一串“foo”不会。

Validator::extend('imageable', function ($attribute, $value, $params, $validator) 
    try 
        ImageManagerStatic::make($value);
        return true;
     catch (\Exception $e) 
        return false;
    
);

这显然只是检查输入是否能够转换为图像。但是,它应该以用例的形式向您展示如何利用干预及其任何方法来创建自定义规则。

【讨论】:

我已在AppServiceProviderboot 方法中添加了您的代码。但是 base64 字符串没有通过验证。我错过了什么吗?扩展是在哪里定义的? @JCarlos 我也将我的放在boot 方法中。你一定有其他问题。 这真的帮助了我在我当前的应用程序中,感谢一百万! 别忘了导入使用 Illuminate\Support\Facades\Validator;使用 Intervention\Image\ImageManagerStatic;【参考方案3】:

在扩展函数里面添加这个

$res= mime_content_type($value);
if ($res == 'image/png' || $res == 'image/jpeg') 
    return $res;

【讨论】:

这仅在您上传真实文件而不是数据 url 或数据库 64 时才有效 这项工作,如果你通过 base64 我尝试了很多次,请试一试

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

如何在 laravel 5.3 中解码 base64

在Grails中解码base64图像[重复]

在 C# 中将 Base64 字节数组解码为图像

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

MiniMagick无法编写解码的Base64图像

如何解码base64 fbx嵌入图像