如何在PHP中检查字符串是否为Base64格式有效的?

88

我有一个字符串,希望使用PHP测试它是否是有效的base64编码。


1
这可能是一个重复的内容。 - Gumbo
注意 base64_encode(base64_decode($data, true)) === $data 技巧。请参见以下评论:Amir's answer @ Detect base64 encoding in PHP?,其中详细讨论了它的多种失败方式和原因。 - mickmackusa
20个回答

146

我知道这个话题很老了,但是使用严格参数并不一定会有帮助。

对于像"I am not base 64 encoded"这样的字符串运行base64_decode不会返回false。

然而,如果你尝试使用严格模式解码字符串,并用base64_encode重新编码它,你可以将结果与原始数据进行比较,以确定是否为有效的base64编码值:

if ( base64_encode(base64_decode($data, true)) === $data){
    echo '$data is valid';
} else {
    echo '$data is NOT valid';
}

5
@Sam,这是因为“test”是一个非常好的base64字符串。它仅使用了base64字符(a-z、A-Z、0-9),并且其长度可以被四整除。这些是有效的base64字符串的唯一要求。当输入“test”时,您期望发生什么? - Kevin
1
如果$data没有有效字符,这将生成一个警告,因为第二个base64_decode将返回FALSE,而第一个将把false编码为布尔值。 base64_decode(false) === $data,因此建议加上@以防止警告。 - Zerquix18
1
@catbadger 但这不是这个问题的重点,它是关于确定数据是否为有效的base64,而字符串“123412341234”是有效的base64,仅仅因为这对你的目的来说不够好,并不意味着它不是有效的base64。在您的情况下,如果您控制数据的编码,您可以在base64编码之前以某种方式标记它,这样您就可以确定在解码后是否应该通过解密。 - PottyBert
1
注意:对于像“test”这样的字符串运行base64_encode(base64_decode($data, true))将返回true,因为它是4的倍数并且仅包含[A-Z、a-z、0-9和+/]。如果剩余长度小于4,则使用“=”字符填充字符串,因此为了解决这个问题,我运行两次base64_decode(使用严格模式)和两次base64_encode... 这将评估所有类型的非base64为false。如果 ( base64_encode(base64_encode(base64_decode(base64_decode($data, true)))) === $data) - Tiamiyu Saheed Oluwatosin
2
谈论“老话题”,嗯...现在已经是2022年了,10年后仍在寻找这个 :)) - Jacky Supit
显示剩余9条评论

32
你可以使用这个函数:
 function is_base64($s)
{
      return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
}

2
我认为这是最接近最佳检测方法的方式。base64_decode(<string, True);即使不正确,也会解码几乎所有内容。虽然可能还有更多可以添加的内容。 - Thomas Schultz
2
我在这里留个便条:小心正则表达式主题的最大大小 https://secure.php.net/manual/en/pcre.constants.php#118538 在 PHP 7 中,至少您将无法以这种方式检查 base64 编码的图像(使用默认 PHP 设置) - Kaktus
这并不会检测无效的base64字符串,它只是检查字符集和格式是否正确。只需在任何非填充的base64编码字符串末尾添加1,它就会简单地解码并忽略附加的1。在这种情况下,严格检查也不起作用。 - DeveloperChris
@DeveloperChris 如果非填充的base64编码字符串长度是4的倍数,则添加到字符串末尾的任何其他字符都应被忽略。但这没问题。 - Karolis

14

仅适用于字符串,您可以使用此函数,在返回 true 之前检查多个 base64 属性:

function is_base64($s){
    // Check if there are valid base64 characters
    if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s)) return false;

    // Decode the string in strict mode and check the results
    $decoded = base64_decode($s, true);
    if(false === $decoded) return false;

    // Encode the string again
    if(base64_encode($decoded) != $s) return false;

    return true;
}

这与我的实现非常相似。首先检查有效字符,然后检查解码/编码字符串并与原始字符串进行比较。 - Matteo Gaggiano
1
函数is_base64($s) { $decoded = base64_decode($s, true); return preg_match('/^[a-zA-Z0-9/\r\n+]*={0,2}$/', $s) && false !== $decoded && base64_encode($decoded) == $s; }的最短版本 - Andrew Rumm
2
对于那些考虑使用安德鲁代码系列的后端开发人员(代码不在浏览器中运行),我建议保持可读性(同时保持性能),而不是将所有代码都写在同一行。并且要使用注释!不要增加技术债务!!! - merlucin

7

这段代码应该可以正常工作,因为如果字符串无效,decode函数会返回FALSE:

if (base64_decode($mystring, true)) {
    // is valid
} else {
    // not valid
}

你可以在文档中了解有关base64_decode函数的更多信息。

29
不要因为这不是确定字符串是否以base64编码的正确方法而进行downvote。它只检查字符串是否具有base64字母表之外的字符。正如Kris所说,使用此方法,字符串“I am not base 64 encoded”不会返回false。 - Maurice
6
这里 Maurice 是正确的。请不要依赖这个答案。它不正确,也不能确定一个字符串是否是 base64 编码。从文档中可以看到:strict: 如果输入包含来自base64字母表之外的字符,则返回FALSE。我不知道为什么 PHP 决定以这种方式处理它,但无论如何,它并不能真正检测出 base64 编码。Kris 的回答是正确的。 - Ben D
这将返回“and”作为有效值。“and”不是有效的(base64编码应该具有可被4整除的字符数)。base64_decode将解码无效的字符串。 - lilHar
@liljoshu 关于“可被4整除”,这对于填充的base64字符串是正确的,但它们不一定需要填充。 - Karolis

4

我认为唯一的方法就是使用 $strict 参数设置为 truebase64_decode() 函数,然后查看它是否返回 false


制作 CW 是因为这是两次重复。 - Pekka
3
因为与另一个类似的答案原因相同而进行了负投票:它只检查字符串是否包含Base64字母表之外的字符。 - Marki

4

我在我的项目中测试了这个方法,它完美地工作。当你将Base64图像传递给这个方法时,如果它有效,它将返回true,否则返回false。让我们试一下并告诉我是否有错误。我会在未来进行编辑和学习。

/**
 * @param $str
 * @return bool
 */
private function isValid64base($str){
    if (base64_decode($str, true) !== false){
        return true;
    } else {
        return false;
    }
}

3

这是一个很老的问题,但我发现以下方法实际上是非常可靠的。它还考虑了那些包含无效字符的奇怪字符串,在验证时可能导致异常。

    public static function isBase64Encoded($str) 
{
    try
    {
        $decoded = base64_decode($str, true);

        if ( base64_encode($decoded) === $str ) {
            return true;
        }
        else {
            return false;
        }
    }
    catch(Exception $e)
    {
        // If exception is caught, then it is not a base64 encoded string
        return false;
    }

}

我从这个页面得到了灵感,并将其适应到了PHP中。


字符串如"ciao"可以成功解码为"r&�"之类的内容,但这并不是一种百分百可靠的方法。 - m47730

3
我尝试了以下步骤:
  • 将字符串使用严格参数进行base64解码。
  • 对上一步的结果进行base64编码。如果结果与原始字符串不同,则原始字符串不是base64编码。
  • 如果结果与原字符串相同,则检查解码后的字符串是否包含可打印字符。我使用了PHP函数ctype_print来检测非可打印字符。该函数会返回false,如果输入字符串包含一个或多个非可打印字符。
下面的代码实现了以上步骤:
public function IsBase64($data) {
    $decoded_data = base64_decode($data, true);
    $encoded_data = base64_encode($decoded_data);
    if ($encoded_data != $data) return false;
    else if (!ctype_print($decoded_data)) return false;

    return true;
}

以上代码可能会返回意外的结果。例如,对于字符串“json”,它将返回false。因为“json”中的字符数量是4的倍数,并且所有字符都在允许的base64编码字符串范围内,所以“json”可能是一个有效的base64编码字符串。似乎我们必须知道原始字符串允许的字符范围,然后检查解码数据是否具有这些字符。


3
如果您正在使用JS进行图片/文件上传的API调用到后端,这可能会有所帮助。
function is_base64_string($string)  //check base 64 encode 
{
  // Check if there is no invalid character in string
  if (!preg_match('/^(?:[data]{4}:(text|image|application)\/[a-z]*)/', $string)){
    return false;
  }else{
    return true;
  }

}

3

好的,大家...终于我找到了一个针对此问题的铁板钉钉的解决方案。使用以下函数检查字符串是否进行了base64编码 -

    private function is_base64_encoded($str) {

       $decoded_str = base64_decode($str);
       $Str1 = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $decoded_str);
       if ($Str1!=$decoded_str || $Str1 == '') {
          return false;
       }
       return true;
    }

唯一有效的。 - Digital Human

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接