29

ユーザーがPOSTHTML5 キャンバス データを使用できるようにするアプリケーションを構築しています。このデータは base64 でエンコードされ、すべてのユーザーに表示されます。データを実際の .png ファイルに解析してサーバーに保存することを検討していますが、base64 ルートを使用すると、画像をデータベースに保存してリクエストを最小限に抑えることができます。画像はユニークで数が少なく、ページが頻繁に更新されることはありません。

少しの jQuery がキャンバス データを取得し、data:image/png;base64,iVBORw...それを次のようにラップする PHP スクリプトに渡します。<img src="$data"></img>

POSTただし、セキュリティは基礎であり、base64 キャンバス データを検証して、リクエストで悪意のあるデータが渡されないようにする必要があります。私の主な関心事は、外部 URL がタグに挿入され、<img>ページの読み込み時にリクエストされるのを防ぐことです。

現在、次のようなセットアップがあります。

$data = (isset($_POST['canvas']) && is_string($_POST['canvas'])) ? $_POST['canvas'] : null;
$base = str_replace('data:image/png;base64,', '', $data);
$regx = '~^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$~'

if ((substr($data, 0, 22)) !== 'data:image/png;base64,')
{
  // Obviously fake, doesn't contain the expected first 22 characters.
  return false;
}

if ((base64_encode(base64_decode($base64, true))) !== $base64)
{
  // Decoding and re-encoding the data fails, something is wrong
  return false;
}

if ((preg_match($regx, $base64)) !== 1) 
{
  // The data doesn't match the regular expression, discard
  return false;
}

return true;

外部 URL がタグに挿入されないように現在の設定が安全であることを確認したいのですが<img>、そうでない場合は、画像データをさらに検証するにはどうすればよいですか?

4

8 に答える 8

31

これを行う 1 つの方法は、実際に base64 データからイメージ ファイルを作成し、イメージ自体を PHP で検証することです。これを行うにはもっと簡単な方法があるかもしれませんが、この方法は確実に機能するはずです。

これは実際には PNG でのみ機能することに注意してください。より多くのファイル タイプ (GIF、JPG) を許可する場合は、いくつかのロジックを追加する必要があります。

<?

$base64 = "[insert base64 code here]";
if (check_base64_image($base64)) {
    print 'Image!';
} else {
    print 'Not an image!';
}

function check_base64_image($base64) {
    $img = imagecreatefromstring(base64_decode($base64));
    if (!$img) {
        return false;
    }

    imagepng($img, 'tmp.png');
    $info = getimagesize('tmp.png');

    unlink('tmp.png');

    if ($info[0] > 0 && $info[1] > 0 && $info['mime']) {
        return true;
    }

    return false;
}

?>
于 2012-09-30T04:55:07.123 に答える
2

私は同じ必要があり、これをしました。これにより、文字列を直接読み取り、getimagesizefromstring 関数を使用してファイルを保存する必要がなくなります。

 public function validateImg($data)
    {
        try {
            $binary = base64_decode(explode(',', $data)[1]);
            $data = getimagesizefromstring($binary);
        } catch (\Exception $e) {
          return false;
        }

        $allowed = ['image/jpeg', 'image/png', 'image/gif'];

        if (!$data) {
            return false;
        }

        if (!empty($data[0]) && !empty($data[0]) && !empty($data['mime'])) {
            if (in_array($data['mime'], $allowed)) {
                return true;
            }
        }

        return false;
    }

于 2020-12-28T14:43:19.543 に答える