PHP 怎么PHP 输入验证

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 输入验证

  1. 核心验证函数
  2. 常见输入类型验证
  3. 表单验证完整示例
  4. 安全最佳实践
  5. 创建可重用的验证类

在 PHP 中,输入验证是确保数据安全性和完整性的关键步骤,以下是 PHP 输入验证的完整指南,包含常见类型、函数、示例和最佳实践。

核心验证函数

过滤器函数(推荐)

PHP 内置的过滤器是最安全、最简洁的方式。

// 验证并过滤整数
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
// 如果验证失败,返回 false
// 验证并过滤邮箱
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
// 验证并过滤 URL
$url = filter_input(INPUT_GET, 'url', FILTER_VALIDATE_URL);
// 验证 IP 地址
$ip = filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP);

常用判断函数

// 检查是否为空
if (empty($_POST['username'])) {
    echo "用户名不能为空";
}
// 检查字符串长度
if (strlen($_POST['password']) < 8) {
    echo "密码至少8位";
}
// 检查是否在范围内
if ($_POST['age'] < 18 || $_POST['age'] > 120) {
    echo "年龄不合法";
}

常见输入类型验证

文本/字符串验证

function validateUsername($username) {
    // 去首尾空格
    $username = trim($username);
    // 检查长度(2-20个字符)
    if (strlen($username) < 2 || strlen($username) > 20) {
        return false;
    }
    // 只允许字母、数字、下划线、中文
    if (!preg_match('/^[a-zA-Z0-9_\x{4e00}-\x{9fa5}]+$/u', $username)) {
        return false;
    }
    return $username;
}

邮箱验证

function validateEmail($email) {
    // 使用过滤器
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        return false;
    }
    // 额外检查域名是否有效(可选)
    $domain = explode('@', $email)[1];
    if (!checkdnsrr($domain, 'MX') && !checkdnsrr($domain, 'A')) {
        return false;
    }
    return $email;
}

数字验证

function validateNumber($input, $min = null, $max = null) {
    // 验证是否为数字
    if (!is_numeric($input)) {
        return false;
    }
    // 转为整数或浮点数
    $number = $input + 0;
    // 范围检查
    if ($min !== null && $number < $min) return false;
    if ($max !== null && $number > $max) return false;
    return $number;
}

URL 验证

function validateUrl($url) {
    // 基本验证
    if (filter_var($url, FILTER_VALIDATE_URL) === false) {
        return false;
    }
    // 只允许 http/https 协议
    $parsed = parse_url($url);
    if (!in_array($parsed['scheme'], ['http', 'https'])) {
        return false;
    }
    return $url;
}

表单验证完整示例

<?php
$errors = [];
$data = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 用户名
    $username = trim($_POST['username'] ?? '');
    if (empty($username)) {
        $errors['username'] = '用户名不能为空';
    } elseif (!preg_match('/^[a-zA-Z0-9_\x{4e00}-\x{9fa5}]{2,20}$/u', $username)) {
        $errors['username'] = '用户名格式不正确(2-20位字母/数字/中文/下划线)';
    } else {
        $data['username'] = $username;
    }
    // 邮箱
    $email = trim($_POST['email'] ?? '');
    if (empty($email)) {
        $errors['email'] = '邮箱不能为空';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors['email'] = '邮箱格式不正确';
    } else {
        $data['email'] = $email;
    }
    // 密码
    $password = $_POST['password'] ?? '';
    $confirm = $_POST['confirm_password'] ?? '';
    if (empty($password)) {
        $errors['password'] = '密码不能为空';
    } elseif (strlen($password) < 8) {
        $errors['password'] = '密码至少8位';
    } elseif ($password !== $confirm) {
        $errors['confirm_password'] = '两次密码不一致';
    } else {
        $data['password'] = password_hash($password, PASSWORD_DEFAULT);
    }
    // 年龄
    $age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 1, 'max_range' => 120]
    ]);
    if ($age === false) {
        $errors['age'] = '年龄必须在1-120之间';
    } else {
        $data['age'] = $age;
    }
    // 如果没有错误,处理数据
    if (empty($errors)) {
        // 保存到数据库或进行其他操作
        header('Location: success.php');
        exit;
    }
}
?>

安全最佳实践

防止 XSS(跨站脚本攻击)

// 输出时使用 htmlspecialchars
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// 或者使用 filter_var
$safe_input = filter_var($user_input, FILTER_SANITIZE_STRING);

防止 SQL 注入

// 使用预处理语句(推荐)
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([':email' => $email]);
// 使用 mysqli 的 real_escape_string
$safe_email = $mysqli->real_escape_string($email);

防止文件上传漏洞

function validateUploadedFile($file) {
    // 检查文件类型
    $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($file['type'], $allowed_types)) {
        return false;
    }
    // 检查文件大小(2MB)
    if ($file['size'] > 2 * 1024 * 1024) {
        return false;
    }
    // 验证文件扩展名
    $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
    if (!in_array(strtolower($extension), ['jpg', 'jpeg', 'png', 'gif'])) {
        return false;
    }
    // 使用 getimagesize 验证图像文件
    if (!getimagesize($file['tmp_name'])) {
        return false;
    }
    return true;
}

创建可重用的验证类

class Validator {
    private $data = [];
    private $errors = [];
    public function __construct($data) {
        $this->data = $data;
    }
    public function required($field, $label = '') {
        if (empty($this->data[$field])) {
            $this->errors[$field] = ($label ?: $field) . '不能为空';
        }
        return $this;
    }
    public function email($field) {
        if (!empty($this->data[$field]) && !filter_var($this->data[$field], FILTER_VALIDATE_EMAIL)) {
            $this->errors[$field] = '邮箱格式不正确';
        }
        return $this;
    }
    public function minLength($field, $min) {
        if (!empty($this->data[$field]) && strlen($this->data[$field]) < $min) {
            $this->errors[$field] = "{$field}至少需要{$min}个字符";
        }
        return $this;
    }
    public function maxLength($field, $max) {
        if (!empty($this->data[$field]) && strlen($this->data[$field]) > $max) {
            $this->errors[$field] = "{$field}不能超过{$max}个字符";
        }
        return $this;
    }
    public function int($field, $min = null, $max = null) {
        $options = [];
        if ($min !== null) $options['min_range'] = $min;
        if ($max !== null) $options['max_range'] = $max;
        if (!empty($this->data[$field])) {
            $value = filter_var($this->data[$field], FILTER_VALIDATE_INT, ['options' => $options]);
            if ($value === false) {
                $this->errors[$field] = "{$field}必须是有效的整数";
            }
        }
        return $this;
    }
    public function validate() {
        return empty($this->errors);
    }
    public function getErrors() {
        return $this->errors;
    }
}
// 使用示例
$validator = new Validator($_POST);
$isValid = $validator
    ->required('username', '用户名')
    ->minLength('username', 2)
    ->maxLength('username', 20)
    ->required('email', '邮箱')
    ->email('email')
    ->required('age', '年龄')
    ->int('age', 1, 120)
    ->validate();
if (!$isValid) {
    print_r($validator->getErrors());
}
  1. 始终验证:不要信任任何用户输入
  2. 使用内置函数:PHP 的过滤器函数是最安全的选择
  3. 输出时转义:使用 htmlspecialchars 防止 XSS
  4. 使用预处理语句:防止 SQL 注入
  5. 验证+清理:验证数据是否符合要求,同时清理不安全的内容
  6. 考虑服务器端验证:不要依赖客户端验证(JavaScript 可以被禁用)

验证在服务器端始终是必要的,客户端验证只是辅助用户体验

抱歉,评论功能暂时关闭!