有没有办法在PHP中检测字符串是否已经进行了base64编码?
我们正在将一些存储从纯文本转换为base64,并且其中的一部分存储在需要更新的Cookie中。如果文本尚未编码,我想重置它们的Cookie,否则保持不变。
对于已经回答过的问题,我很抱歉回复晚了。但是我不认为base64_decode($x,true)是解决这个问题的好方法。实际上,可能没有一个非常好的方法可以针对任何输入都有效。例如,我可以将许多错误的值放入$x中,并且不会得到错误的返回值。
var_dump(base64_decode('wtf mate',true));
string(5) "���j�"
var_dump(base64_decode('This is definitely not base64 encoded',true));
string(24) "N���^~)��r��[jǺ��ܡם"
我认为除了严格的返回值检查外,您还需要进行解码后的验证。最可靠的方法是,如果您能对已知的一组可能值进行解码,然后进行检查。
另一个更普遍的解决方案(长字符串更接近100%准确,对于短字符串不准确)是检查输出是否有很多超出正常范围的 utf-8(或任何编码方式)字符。
请参见以下示例:
<?php
$english = array();
foreach (str_split('az019AZ~~~!@#$%^*()_+|}?><": Iñtërnâtiônàlizætiøn') as $char) {
echo ord($char) . "\n";
$english[] = ord($char);
}
echo "Max value english = " . max($english) . "\n";
$nonsense = array();
echo "\n\nbase64:\n";
foreach (str_split(base64_decode('Not base64 encoded',true)) as $char) {
echo ord($char) . "\n";
$nonsense[] = ord($char);
}
echo "Max nonsense = " . max($nonsense) . "\n";
?>
结果:
Max value english = 195
Max nonsense = 233
if ( $maxDecodedValue > 200 ) {} //decoded string is Garbage - original string not base64 encoded
else {} //decoded string is useful - it was base64 encoded
你应该使用解码值的mean()而不是max(),我在这个示例中只是使用了max(),因为PHP中没有内置的mean()函数。您使用哪种度量(mean、max等)针对什么阈值(例如200)取决于您的预估使用情况。
总之,唯一的胜利之举是不参与其中。我会尽量避免首先辨别base64。
function is_base64_encoded($data)
{
if (preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $data)) {
return TRUE;
} else {
return FALSE;
}
};
is_base64_encoded("iash21iawhdj98UH3"); // true
is_base64_encoded("#iu3498r"); // false
is_base64_encoded("asiudfh9w=8uihf"); // false
is_base64_encoded("a398UIhnj43f/1!+sadfh3w84hduihhjw=="); // false
我也遇到了同样的问题,最终找到了这个解决方案:
if ( base64_encode(base64_decode($data)) === $data){
echo '$data is valid';
} else {
echo '$data is NOT valid';
}
迟做总比不做好:你可以使用mb_detect_encoding()
函数来判断编码后的字符串是否为文本类型:
function is_base64_string($s) {
// first check if we're dealing with an actual valid base64 encoded string
if (($b = base64_decode($s, TRUE)) === FALSE) {
return FALSE;
}
// now check whether the decoded data could be actual text
$e = mb_detect_encoding($b);
if (in_array($e, array('UTF-8', 'ASCII'))) { // YMMV
return TRUE;
} else {
return FALSE;
}
}
更新 对于那些喜欢简短的人
function is_base64_string_s($str, $enc=array('UTF-8', 'ASCII')) {
return !(($b = base64_decode($str, TRUE)) === FALSE) && in_array(mb_detect_encoding($b), $enc);
}
555
,那么这个函数将返回 true
,而 555 不是有效的 base 64 编码。 - veebase64_decode()
确实会解码错误,但OP询问如何检测base64编码字符串,而5555不是base64编码字符串(抱歉,我错了)。因此,该函数无法检测到这一点。我发现有很多无效字符是ascii
或utf-8
格式的。在这种情况下,mb_detect_encoding()
不能用于100%检测已解码的base64字符串。 - vee我们可以将三件事情合并成一个函数来检查给定的字符串是否是有效的base64编码。
function validBase64($string)
{
$decoded = base64_decode($string, true);
$result = false;
// Check if there is no invalid character in string
if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {$result = false;}
// Decode the string in strict mode and send the response
if (!$decoded) {$result = false;}
// Encode and compare it to original one
if (base64_encode($decoded) != $string) {$result = false;}
return $result;
}
我正准备在php中创建一个base64开关,这是我的做法:
function base64Toggle($str) {
if (!preg_match('~[^0-9a-zA-Z+/=]~', $str)) {
$check = str_split(base64_decode($str));
$x = 0;
foreach ($check as $char) if (ord($char) > 126) $x++;
if ($x/count($check)*100 < 30) return base64_decode($str);
}
return base64_encode($str);
}
return base64_encode($str)
的位置使用 return false
,在 return base64_decode($str)
的位置使用 return true
)。我很感激你在博客上对此进行了解释。 - Fr0zenFyr如果输入不是有效的base64编码数据,base64_decode()
将不会返回FALSE。使用imap_base64()
代替,它会在$text中包含Base64字母表外的字符时返回FALSE。imap_base64()参考资料
base64_decode($string, true)
相同,即严格形式。 - Fr0zenFyrif(empty(htmlspecialchars(base64_decode($string, true)))) {
return false;
}
如果解码的$string
无效,例如:"node"、"123"、""等,则会返回false。请注意保留html标记。$is_base64 = function(string $string) : bool {
$zero_one = ['MA==', 'MQ=='];
if (in_array($string, $zero_one)) return TRUE;
if (empty(htmlspecialchars(base64_decode($string, TRUE))))
return FALSE;
return TRUE;
};
var_dump('*** These yell false ***');
var_dump($is_base64(''));
var_dump($is_base64('This is definitely not base64 encoded'));
var_dump($is_base64('node'));
var_dump($is_base64('node '));
var_dump($is_base64('123'));
var_dump($is_base64(0));
var_dump($is_base64(1));
var_dump($is_base64(123));
var_dump($is_base64(1.23));
var_dump('*** These yell true ***');
var_dump($is_base64(base64_encode('This is definitely base64 encoded')));
var_dump($is_base64(base64_encode('node')));
var_dump($is_base64(base64_encode('123')));
var_dump($is_base64(base64_encode(0)));
var_dump($is_base64(base64_encode(1)));
var_dump($is_base64(base64_encode(123)));
var_dump($is_base64(base64_encode(1.23)));
var_dump($is_base64(base64_encode(TRUE)));
var_dump('*** Should these yell true? Might be edge cases ***');
var_dump($is_base64(base64_encode('')));
var_dump($is_base64(base64_encode(FALSE)));
var_dump($is_base64(base64_encode(NULL)));
$encoded=base64_encode(json_encode($data));
function isData($test_string){
if(base64_decode($test_string,true)&&json_decode(base64_decode($test_string))){
return true;
}else{
return false;
}
function isNotData($test_string){
if(base64_decode($test_string,true)&&json_decode(base64_decode($test_string))){
return false;
}else{
return true;
}
感谢本帖中之前所有回答者的贡献 :)
json_encode()
,这里就会出现问题。aGVsbG8=是hello的base64编码字符串。isData('aGVsbG8=')
应该为true
,但却得到了false
。json_decode()
无法正确检测解码后的base64字符串。 - vee
is_base64_encoded("a398UIhnj43f/1!+sadfh3w84hduihhjw=="); // true
在我的测试中返回 FALSE。 - Dylan