PHP filter_var URL
PHP filter_var URL
为了验证用户输入的 URL 路径,我使用了 PHP filter_var 函数。
输入仅包含路径 (/path/path/script.php)。
验证路径时,我添加了主机。我正在玩一点,测试输入验证等。这样做,我注意到过滤器 URL 函数的奇怪(??)行为。
代码:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
var_dump(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); //valid
有人可以解释为什么这是有效的 URL 吗?谢谢!
简短的回答是,PHP FILTER_VALIDATE_URL 仅根据 RFC 2396 检查 URL,而您的 URL 虽然很奇怪,但根据上述标准是有效的。
长答案:
您使用的过滤器被声明为符合 RFC,所以让我们检查一下该标准 (RFC 2396)。
用于解析 URL 并列在那里的正则表达式是:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12 3 4 5 6 7 8 9
其中:
scheme =
authority =
path =
query =
fragment =
正如我们所见,“:”字符仅在方案的上下文中保留,从那时起“:”是公平游戏(标准文本支持)。例如,它在 http: 方案中被自由使用来表示端口。斜杠也可以出现在任何地方,并且没有什么可以禁止 URL 在中间某处有一个“//”。所以中间的"http://"应该是有效的。
让我们看看您的 URL 并尝试将其与此正则表达式相匹配:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
//Escaped a couple slashes to make things work, still the same regexp
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
echo '<p>'.$result_rfc.'</p>';
测试returns'1'所以这个url是有效的。这是意料之中的,因为规则不会像我们看到的那样声明中间有类似 'http://' 的 urls 是无效的。 PHP 简单地用 FILTER_VALIDATE_URL 反映了这种行为。
如果你想要更严格的测试,你需要自己编写所需的代码。例如,您可以防止“://”出现多次:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
if (substr_count($url,'://') != 1) {
$result_non_rfc = false;
} else {
$result_non_rfc = $result_rfc;
}
您也可以尝试调整正则表达式本身。
为了验证用户输入的 URL 路径,我使用了 PHP filter_var 函数。 输入仅包含路径 (/path/path/script.php)。
验证路径时,我添加了主机。我正在玩一点,测试输入验证等。这样做,我注意到过滤器 URL 函数的奇怪(??)行为。
代码:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
var_dump(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); //valid
有人可以解释为什么这是有效的 URL 吗?谢谢!
简短的回答是,PHP FILTER_VALIDATE_URL 仅根据 RFC 2396 检查 URL,而您的 URL 虽然很奇怪,但根据上述标准是有效的。
长答案:
您使用的过滤器被声明为符合 RFC,所以让我们检查一下该标准 (RFC 2396)。
用于解析 URL 并列在那里的正则表达式是:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12 3 4 5 6 7 8 9
其中:
scheme =
authority =
path =
query =
fragment =
正如我们所见,“:”字符仅在方案的上下文中保留,从那时起“:”是公平游戏(标准文本支持)。例如,它在 http: 方案中被自由使用来表示端口。斜杠也可以出现在任何地方,并且没有什么可以禁止 URL 在中间某处有一个“//”。所以中间的"http://"应该是有效的。
让我们看看您的 URL 并尝试将其与此正则表达式相匹配:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
//Escaped a couple slashes to make things work, still the same regexp
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
echo '<p>'.$result_rfc.'</p>';
测试returns'1'所以这个url是有效的。这是意料之中的,因为规则不会像我们看到的那样声明中间有类似 'http://' 的 urls 是无效的。 PHP 简单地用 FILTER_VALIDATE_URL 反映了这种行为。
如果你想要更严格的测试,你需要自己编写所需的代码。例如,您可以防止“://”出现多次:
$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
if (substr_count($url,'://') != 1) {
$result_non_rfc = false;
} else {
$result_non_rfc = $result_rfc;
}
您也可以尝试调整正则表达式本身。