簡體   English   中英

使用 PHP 處理動畫 GIF 的最佳方法

[英]Best way to handle animated GIF with PHP

首先,對不起我的語法不好。 英語不是我的主要語言...

我正在開發一個完全 AJAXed wordpress 主題,其中包含前端線程提交表單,我想添加動畫 GIF 支持。

我寫了一個使用imagick庫的代碼PHP代碼:

 // there is also another function that
 checks image's exif, size, width, height, finfo and retuns true if all good.


  // first imagick resize is basicly re-coding the image to kill shell/hack codes in the gif.
  $imagick =  new Imagick($image['tmp_name']);
  $imagick = $imagick->coalesceImages();

  foreach($imagick as $frame){
    $frame->scaleImage($width, 0);

  }

  $imagick = $imagick->deconstructImages();
  $imagick->writeImages($new_image_name, true);
  $imagick->destroy();

 // and this one for the thumbnail of the post.
 $imagick =  new Imagick($image['tmp_name']);

  $imagick = $imagick->coalesceImages();

  foreach($imagick as $frame){
  $frame->scaleImage(wp_get_registered_image_subsizes()["left-frame-thumbnail"]["width"], 0);
  }
    
      $imagick = $imagick->deconstructImages();
      $imagick->writeImages($new_image_name, true);
      $imagick->destroy();

代碼就像魅力一樣,但我注意到這是一個昂貴的代碼。 我的意思是,如果用戶上傳一個大的 gif 文件,我認為它會導致 CPU 峰值。

如果我將 GIF 大小限制為 2MB 則沒關系,因為其他問題是幀數。 我們知道,當我們調整 GIF 的大小時,我們會拆分所有幀,調整它們的大小並將它們重新連接在一起。 有很多 300kb 左右的 gif,但其中包含 50 多個幀。 所以幀數也是服務器CPU的問題。

然后我說; 嘿。 讓我們使用 Javascript 在客戶端調整 gif 的大小。 我寫了一個在客戶端調整 gif 大小的代碼。 這確實非常有效。

我在服務器端編寫了一個代碼來獲取調整大小的 2 gif 文件並將它們直接保存到服務器(同時檢查它們的 exif、尺寸、finfo)。 一切都很好,服務器CPU很好。

但是:我注意到了第一條規則。 “永遠不要相信來自客戶端的數據。”

如果我在客戶端調整它的大小,那很好。 調整大小會殺死圖像中的 hack/shell 代碼。 但是,如果用戶發送假的 2 兩個看起來像是剛剛調整大小並通過控制台或其他方式來自表單的文件怎么辦?

我的 ajax 提交中已經有一個 CSRF 令牌,但我確信這還不夠。

摘要:處理動畫 GIF 的最佳方式是什么? 我做錯了什么。

在客戶端拆分為幀、調整大小和重新加入所有內容對於非惡意用戶來說是一個很好的減少服務器負載的方法。 但是,攻擊者仍然可以向您的 PHP 發送任何請求,包括帶有大量大幀的巨大 gif - 他們根本不需要運行您的 javascript。 因此,您完全正確,這是您應該減輕的潛在拒絕服務。 用戶輸入不可信。

我想到了一些想法(請注意,我從未真正使用過動畫 gif)。 它們都圍繞輸入驗證。

我不確定服務器上究竟需要很長時間,但我想這不是分割圖像,更像是調整每一幀的大小。 由於您的 javascript 應該在客戶端上調整 gif 的大小,因此收到的任何 gif 都應該只包含限制大小的幀。 您可以拆分收到的 gif 並檢查第一幀 - 如果它太大,您可以立即拒絕整個請求,這通常不會發生。 (也許您甚至不必拆分它來告訴大小?)

此外,您在客戶端拆分並逐個發送它們的想法很棒,它承擔了從服務器拆分的負載,您可以(並且應該)仍然檢查服務器上幀的大小。 請注意,在這種情況下,不僅第一個可能太大,攻擊者可以發送任何東西。

您還可以檢查幀數,並設置一個最大值,因為沒有它,這兩種方式都是潛在的拒絕服務,因為攻擊者可以只發送一個 10x10 像素的 gif,但是 100 萬幀(我不是確定 gif 格式是否有限制,但你明白了)。

另一種旁注是,無論您使用什么庫來處理服務器上的 gif,都可能容易受到來自惡意圖像的不同攻擊。 例如,Imagemagick 過去就存在一些此類漏洞。 因此,為了使這更安全,除了隨着庫的新版本發布而進行的明顯升級之外,您可以在不同的服務器上運行圖像處理,類似於后台作業處理器。 僅允許對該服務器進行非常有限的訪問並應用通用的強化最佳實踐可以幫助遏制任何未來的妥協,並且還可以限制拒絕服務攻擊的影響。

您還應該對此圖像上傳端點應用某種速率限制,因為上傳 1000 張 100 幀的圖像甚至比 100000 幀的 1 張圖像還要糟糕。 因此,應該限制用戶執行此操作的頻率(或在給定時間范圍內有多少圖像)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM