Skip to content

PHP 过滤器

PHP 过滤器用于验证和清理数据,特别是来自外部来源的数据,如用户输入、数据库或 API。

  • 验证数据: 确定数据是否符合预期的规则或格式(例如,它是一个有效的电子邮件地址吗?它是一个在特定范围内的整数吗?)。
  • 清理数据: 修改数据以移除潜在有害的字符或元素,或确保其符合特定格式(例如,移除 HTML 标签,编码特殊字符)。

PHP 的过滤器扩展提供了一种标准化方式来执行数据验证和清理,使此过程比单独使用手动检查或正则表达式 更容易、更安全,并且通常更快。

您可以使用 filter_list() 函数列出所有可用的过滤器:

<?php
echo "<table>";
echo "<tr><th>过滤器名称</th><th>过滤器 ID</th></tr>";
foreach (filter_list() as $filter) {
echo '<tr><td>' . htmlspecialchars($filter) . '</td><td>' . filter_id($filter) . '</td></tr>';
}
echo "</table>";
?>

Web 应用程序不断与外部数据交互。永远不要隐式信任外部数据!来源包括:

  • 来自 HTML 表单的用户输入($_GET、$_POST)
  • Cookie ($_COOKIE)
  • 来自 Web 服务或 API 的数据
  • 服务器环境变量($_SERVER)
  • 数据库查询结果

安全警告:未能验证和清理外部数据可能导致严重的安全漏洞(如跨站脚本 (XSS)、SQL 注入、远程代码执行),并可能破坏应用程序的功能。PHP 过滤器提供了关键的防御层。

filter_var() 函数是使用指定过滤器过滤单个变量的核心函数。

语法:

filter_var(mixed $value, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed

参数:

  • value:您要过滤的变量(值)。
  • filter:要应用的过滤器 ID(例如,FILTER_VALIDATE_EMAIL、FILTER_SANITIZE_NUMBER_INT)。默认为 FILTER_DEFAULT(等同于 FILTER_UNSAFE_RAW)。
  • options:与指定过滤器一起使用的选项或标志的关联数组。

返回值:成功时返回过滤后的数据,如果过滤器验证失败则返回 false,如果使用了 FILTER_NULL_ON_FAILURE 标志且验证失败则返回 null。

清理旨在通过移除或编码不需要的元素来使数据安全,通常用于输出或存储。

示例:清理字符串以用于 HTML 输出(防止 XSS)

Section titled “示例:清理字符串以用于 HTML 输出(防止 XSS)”

使用 htmlspecialchars() 将特殊字符转换为 HTML 实体。这是在将用户提供的文本输出到 HTML 中时防止 XSS 的标准方法。

<?php
$userInput = '<script>alert("XSS");</script> harmless text';
// 清理以确保安全的 HTML 输出
$safeOutput = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
echo $safeOutput;
// 输出: &lt;script&gt;alert(&quot;XSS&quot;);&lt;/script&gt; harmless text
// <script> 标签被无害地渲染为文本,而不是被执行。
?>

注意:FILTER_SANITIZE_STRING 和 FILTER_SANITIZE_STRIPPED 在 PHP 8.0 中已弃用,并在 PHP 8.1 中移除。请酌情使用 htmlspecialchars()、strip_tags()(谨慎使用)或特定的清理器,如 FILTER_SANITIZE_EMAIL。

移除电子邮件地址中非法字符。

<?php
$email = ' john.doe(comment)@example.com\n';
$sanitizedEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
echo $sanitizedEmail; // 输出: john.doe@example.com
?>

验证检查数据是否符合特定条件。

检查变量是否包含有效的整数值。

<?php
$input = "100"; // 包含数字的字符串
$zeroInput = "0";
$invalidInput = "hello";
// 推荐方式:使用 FILTER_NULL_ON_FAILURE
$validatedInt = filter_var($input, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
if ($validatedInt !== null) {
echo "'{$input}' is a valid integer. Value: " . $validatedInt . "<br>";
} else {
echo "'{$input}' is not a valid integer.<br>";
}
$validatedZero = filter_var($zeroInput, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
if ($validatedZero !== null) {
// 正确处理 0 作为有效整数
echo "'{$zeroInput}' is a valid integer. Value: " . $validatedZero . "<br>";
} else {
echo "'{$zeroInput}' is not a valid integer.<br>";
}
$validatedInvalid = filter_var($invalidInput, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
if ($validatedInvalid !== null) {
echo "'{$invalidInput}' is a valid integer. Value: " . $validatedInvalid . "<br>";
} else {
echo "'{$invalidInput}' is not a valid integer.<br>";
}
?>

解释:使用 FILTER_NULL_ON_FAILURE 会使函数在验证失败时返回 null,这避免了 filter_var 在失败时返回 false 的常见陷阱,因为 false 可能会与输入值 0 或 false 混淆。

检查变量是否包含有效的 IPv4 或 IPv6 地址。

<?php
$ip = "127.0.0.1";
if (filter_var($ip, FILTER_VALIDATE_IP)) {
echo htmlspecialchars($ip) . " is a valid IP address.<br>";
} else {
echo htmlspecialchars($ip) . " is not a valid IP address.<br>";
}
$ipv6 = "::1"; // 示例 IPv6 回环地址
if (filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
echo htmlspecialchars($ipv6) . " is a valid IPv6 address.<br>";
} else {
echo htmlspecialchars($ipv6) . " is not a valid IPv6 address.<br>";
}
?>

示例:清理和验证电子邮件地址

Section titled “示例:清理和验证电子邮件地址”

一个常见模式:先清理,后验证。

<?php
$email = ' john.doe(remove)@example .com ';
// 1. 清理:移除非法字符和空白
$sanitizedEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
// 2. 验证:检查清理后的结果是否是有效的电子邮件格式
if (filter_var($sanitizedEmail, FILTER_VALIDATE_EMAIL)) {
echo "'" . htmlspecialchars($sanitizedEmail) . "' is a valid email address.";
} else {
echo "'" . htmlspecialchars($sanitizedEmail) . "' is not a valid email address (Original input: '" . htmlspecialchars($email) ."').";
}
?>

URL 的类似模式。

<?php
$url = ' https:// w ww. example.com/path?query=yes ';
// 1. 清理:移除非法 URL 字符
$sanitizedUrl = filter_var($url, FILTER_SANITIZE_URL);
// 2. 验证:检查清理后的结果是否是有效的 URL 格式
if (filter_var($sanitizedUrl, FILTER_VALIDATE_URL)) {
echo "'" . htmlspecialchars($sanitizedUrl) . "' is a valid URL.";
} else {
echo "'" . htmlspecialchars($sanitizedUrl) . "' is not a valid URL (Original input: '" . htmlspecialchars($url) ."').";
}
?>

有关所有过滤器类型、标志和高级用法(如使用 filter_input_array 或 filter_var_array 过滤数组)的完整参考,请查阅官方 PHP 文档: