我有一个PHP网站,注册用户可以上传头像。其中一个限制是,人们只能上传只包含字母数字字符的.jpg或.jpeg文件,其他任何内容都会被拒绝。这是为了确保我只上传像“avatar.jpg”,而不是“evilcode.php”或“secretcode.php.jpg”。我还计划进行其他检查,但现在我无法完成第一步。
我正在使用这个正则表达式:
[a-zA-Z0-9]{1,150}+\.+(jpe?g)
这是我目前正在使用的代码。该函数从另一个php文件调用,$ _FILES ['avatar']作为参数。
public function updateAvatar($avatar)
{
$regex = '^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$';
$name = $avatar['name'];
$result = preg_match_all($regex, $name);
if($result === 1)
{
return true;
} else
{
return false;
}
}
当上传“avatar.jpg”,“code.php”或“duck.gif”时,这总是返回false。根据PHP手册,这段代码应该是正确的。该方法返回一个整数或一个布尔值,并警告您应该使用===,而不是==来比较结果。有谁知道我做错了什么?
答案 0 :(得分:2)
当您通过正则表达式检查传入文件时,可以使用可执行的mime上传exploit file,因此您必须检查文件的mime以便安全上传:
public function updateAvatar($avatar)
{
$available_mimes = array(
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpg',
'iejpg' => 'image/pjpeg' // this mime sent Internet Explorer for jpg files
);
if(in_array($avatar['type'], $available_mimes)
{
return true;
}
else
{
return false;
}
}
关于你的正则表达式函数:
public function updateAvatar($avatar)
{
// Use regex with ignore case flag (for validating jpg and JPG)
// Uncomment next line, if you want to check files with "_" symbols at name
// if(preg_match('/^(\w+)\.(jpe?g)$/i', $avatar['name']))
if(preg_match('/^([a-z0-9]+)\.(jpe?g)$/i', $avatar['name']))
{
return true;
}
else
{
return false;
}
}
尝试使用preg_match()
答案 1 :(得分:1)
你的正则表达式没有分隔符:
/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/
并且在检查单个头像文件名时不需要preg_match_all()
:
public function updateAvatar($avatar)
{
$regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';
$name = $avatar['name'];
if(preg_match($regex, $name))
return true;
return false;
}
但是你最好将你的正则表达式更改为:
/^[a-zA-Z0-9]{1,100}\.(jpe?g)$/
在不需要量词后的+
符号,您也不应该在名称末尾验证多个dot
作为您的要求。
答案 2 :(得分:0)
我看到两个问题。首先,PHP的RegEx函数期望模式被您选择的分隔符字符包围(正则表达式选项位于结束分隔符之后)。
例如:$regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';
或$regex = '|^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$|';
其次,您同时使用{1,100}
(“指定类的一到100个字符串”)以及+
(“指定类的一个或多个字符”)。只使用其中一种。
答案 3 :(得分:0)
尝试使用此,
/\.(jpg|jpeg|png|gif)(?:[\?\#].*)?$/i
答案 4 :(得分:-1)
在你的正则表达式中添加分隔符,试试这个:
$regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';
// ^ ^