PHP Filter 函数

PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤,确保数据的安全性和有效性。

PHP Filter 简介

PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤。

Filter 扩展提供了两种主要类型的过滤器:

  • 验证过滤器 - 用于验证数据是否符合特定格式(如邮箱、URL、IP地址等)
  • 清理过滤器 - 用于清理数据,移除或编码不安全的字符
为什么使用过滤器?
  • 防止跨站脚本攻击(XSS)
  • 防止SQL注入攻击
  • 确保数据的完整性和正确性
  • 标准化用户输入

安装说明

Filter 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

检查Filter扩展是否可用
// 检查Filter扩展是否已启用
if (extension_loaded('filter')) {
    echo 'Filter 扩展已启用';
} else {
    echo 'Filter 扩展未启用';
}

// 获取所有可用的过滤器
$filters = filter_list();
echo "可用的过滤器:\n";
print_r($filters);

PHP Filter 函数列表

函数 描述 版本
filter_has_var() 检查是否存在指定输入类型的变量。 PHP 5+
filter_id() 返回指定过滤器的 ID 号。 PHP 5+
filter_input() 从脚本外部获取输入,并进行过滤。 PHP 5+
filter_input_array() 从脚本外部获取多项输入,并进行过滤。 PHP 5+
filter_list() 返回包含所有得到支持的过滤器的一个数组。 PHP 5+
filter_var_array() 获取多个变量,并进行过滤。 PHP 5+
filter_var() 获取一个变量,并进行过滤。 PHP 5+
filter_input_validate() 验证输入并返回验证结果。 PHP 7.4+
filter_validate_deep() 深度验证嵌套数组。 PHP 8.1+

PHP 过滤器列表

ID 名称 常量值 描述
验证过滤器 (Validation Filters)
FILTER_VALIDATE_INT 257 把值作为整数来验证。
FILTER_VALIDATE_BOOLEAN 258 把值作为布尔选项来验证。如果是 "1"、"true"、"on" 和 "yes",则返回 TRUE。如果是 "0"、"false"、"off"、"no" 和 "",则返回 FALSE。否则返回 NULL。
FILTER_VALIDATE_FLOAT 259 把值作为浮点数来验证。
FILTER_VALIDATE_REGEXP 272 根据 regexp(一种兼容 Perl 的正则表达式)来验证值。
FILTER_VALIDATE_URL 273 把值作为 URL 来验证。
FILTER_VALIDATE_EMAIL 274 把值作为 e-mail 地址来验证。
FILTER_VALIDATE_IP 275 把值作为 IP 地址来验证,只限 IPv4 或 IPv6 或不是来自私有或者保留的范围。
FILTER_VALIDATE_MAC 276 验证 MAC 地址。
FILTER_VALIDATE_DOMAIN 277 验证域名。
清理过滤器 (Sanitization Filters)
FILTER_SANITIZE_STRING 513 去除标签,去除或编码特殊字符。
FILTER_SANITIZE_STRIPPED 513 "string" 过滤器的别名。
FILTER_SANITIZE_ENCODED 514 URL-encode 字符串,去除或编码特殊字符。
FILTER_SANITIZE_SPECIAL_CHARS 515 HTML 转义字符 '"<>& 以及 ASCII 值小于 32 的字符。
FILTER_SANITIZE_EMAIL 517 删除所有字符,除了字母、数字以及 !#$%&'*+-/=?^_`{|}~@.[]
FILTER_SANITIZE_URL 518 删除所有字符,除了字母、数字以及 $-_.+!*'(),{}|\^~[]`<>#%";/?:@&=
FILTER_SANITIZE_NUMBER_INT 519 删除所有字符,除了数字和 +-
FILTER_SANITIZE_NUMBER_FLOAT 520 删除所有字符,除了数字、+- 以及 .,eE
FILTER_SANITIZE_MAGIC_QUOTES 521 应用 addslashes()。
FILTER_SANITIZE_FULL_SPECIAL_CHARS 522 等价于 htmlspecialchars(),将特殊字符转换为HTML实体。
FILTER_UNSAFE_RAW 516 不进行任何过滤,去除或编码特殊字符。
其他过滤器
FILTER_CALLBACK 1024 调用用户自定义函数来过滤数据。

使用示例

基本验证示例
// 验证整数
$int = '123';
if (filter_var($int, FILTER_VALIDATE_INT)) {
    echo "$int 是有效的整数\n";
} else {
    echo "$int 不是有效的整数\n";
}

// 验证邮箱
$email = 'john@example.com';
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "$email 是有效的邮箱地址\n";
} else {
    echo "$email 不是有效的邮箱地址\n";
}

// 验证URL
$url = 'https://www.example.com';
if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo "$url 是有效的URL\n";
} else {
    echo "$url 不是有效的URL\n";
}

// 验证IP地址
$ip = '192.168.1.1';
if (filter_var($ip, FILTER_VALIDATE_IP)) {
    echo "$ip 是有效的IP地址\n";
} else {
    echo "$ip 不是有效的IP地址\n";
}

// 验证布尔值
$bool = 'true';
$result = filter_var($bool, FILTER_VALIDATE_BOOLEAN);
echo "布尔验证结果: ";
var_dump($result);
数据清理示例
// 清理字符串中的HTML标签
$string = "<script>alert('xss')</script>Hello <b>World</b>";
$clean = filter_var($string, FILTER_SANITIZE_STRING);
echo "清理后的字符串: " . $clean . "\n";

// 清理邮箱地址
$email = "john.(doe)@exa//mple.com";
$clean_email = filter_var($email, FILTER_SANITIZE_EMAIL);
echo "清理后的邮箱: " . $clean_email . "\n";

// 清理URL
$url = "http://www.example.com/<script>alert(1)</script>";
$clean_url = filter_var($url, FILTER_SANITIZE_URL);
echo "清理后的URL: " . $clean_url . "\n";

// 清理整数
$number = "123abc456";
$clean_number = filter_var($number, FILTER_SANITIZE_NUMBER_INT);
echo "清理后的整数: " . $clean_number . "\n";

// HTML特殊字符转义
$html = '<p>Test "quotes" & specials</p>';
$escaped = filter_var($html, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
echo "转义后的HTML: " . $escaped . "\n";
处理用户输入
// 使用 filter_input() 获取和过滤GET参数
$name = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_STRING);
$age = filter_input(INPUT_GET, 'age', FILTER_VALIDATE_INT);
$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);

echo "姓名: " . ($name ?: '未提供') . "\n";
echo "年龄: " . ($age ?: '无效或未提供') . "\n";
echo "邮箱: " . ($email ?: '无效或未提供') . "\n";

// 使用 filter_input_array() 批量处理
$filters = [
    'username' => FILTER_SANITIZE_STRING,
    'email'    => FILTER_VALIDATE_EMAIL,
    'age'      => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 120]],
    'website'  => FILTER_VALIDATE_URL,
    'score'    => ['filter' => FILTER_VALIDATE_FLOAT, 'options' => ['min_range' => 0, 'max_range' => 100]]
];

$input = filter_input_array(INPUT_GET, $filters);

echo "批量验证结果:\n";
print_r($input);
高级过滤器选项
// 自定义验证规则
$options = [
    'options' => [
        'min_range' => 1,
        'max_range' => 100
    ],
    'flags' => FILTER_FLAG_ALLOW_OCTAL | FILTER_FLAG_ALLOW_HEX
];

$number = '0x1A'; // 十六进制 26
if (filter_var($number, FILTER_VALIDATE_INT, $options)) {
    echo "$number 是在1-100范围内的有效整数\n";
}

// IP地址验证选项
$ipv4 = '192.168.1.1';
$ipv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334';

// 验证IPv4
if (filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    echo "$ipv4 是有效的IPv4地址\n";
}

// 验证IPv6
if (filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
    echo "$ipv6 是有效的IPv6地址\n";
}

// 验证私有IP
$private_ip = '10.0.0.1';
if (filter_var($private_ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
    echo "$private_ip 不是私有IP地址\n";
} else {
    echo "$private_ip 是私有IP地址\n";
}

// 自定义回调过滤器
function custom_filter($value) {
    // 移除所有空格并转换为大写
    $value = str_replace(' ', '', $value);
    return strtoupper($value);
}

$data = 'hello world';
$filtered = filter_var($data, FILTER_CALLBACK, ['options' => 'custom_filter']);
echo "自定义过滤结果: " . $filtered . "\n";
最佳实践
  • 始终验证和清理用户输入
  • 根据上下文选择适当的过滤器类型
  • 对于关键数据,使用多重验证
  • 使用 filter_input() 和 filter_input_array() 处理外部输入
  • 为整数和浮点数设置合理的范围限制
  • 自定义过滤器回调时要确保安全性
  • 定期检查过滤器扩展的更新和新功能
安全注意事项
  • 不要信任任何用户输入:始终假设用户输入是恶意的
  • 使用适当的过滤器:根据数据类型选择正确的过滤器
  • 多重防御:不要依赖单一的安全措施
  • 及时更新:保持PHP和过滤器扩展的最新版本
  • 日志记录:记录可疑的输入尝试
  • 错误处理:不要向用户显示详细的错误信息