php数据验证 + 过滤 + 参数绑定

绝对不建议直接操作 $_POST 这是一个非常重要的安全实践。

❌ 为什么不建议直接使用 $_POST

直接使用 $_POST 的问题:

// ❌ 危险做法 - 千万不要这样写!
$sql = "INSERT INTO users (username, email) VALUES ('{$_POST['username']}', '{$_POST['email']}')";
// SQL注入漏洞!

✅ 推荐的最佳实践

1. 数据验证 + 过滤 + 参数绑定

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
    // 方法一:从 $_POST 获取(表单格式)
    $username = $_POST['username'] ?? '';
    $email = $_POST['email'] ?? '';
    
    // 方法二:从 JSON 获取(推荐用于 Vue/Ajax)
    $input = json_decode(file_get_contents('php://input'), true) ?? [];
    $username = $input['username'] ?? '';
    $email = $input['email'] ?? '';
    
    // 1. 数据验证
    $errors = [];
    
    if (empty($username) || strlen($username) < 2) {
        $errors[] = '用户名至少2个字符';
    }
    
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = '邮箱格式不正确';
    }
    
    if (!empty($errors)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'errors' => $errors]);
        exit;
    }
    
    // 2. 数据清理
    $username = trim($username);
    $username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    
    // 3. 创建数据数组
    $data = [
        'username' => $username,
        'email' => $email,
        'created_at' => date('Y-m-d H:i:s'),
        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? ''
    ];
    
    // 4. 插入数据库(使用预处理语句)
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'username', 'password');
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        
        $stmt = $pdo->prepare("INSERT INTO users (username, email, created_at, ip_address) VALUES (:username, :email, :created_at, :ip_address)");
        
        $stmt->execute([
            ':username' => $data['username'],
            ':email' => $data['email'],
            ':created_at' => $data['created_at'],
            ':ip_address' => $data['ip_address']
        ]);
        
        echo json_encode(['success' => true, 'message' => '数据插入成功', 'id' => $pdo->lastInsertId()]);
        
    } catch (PDOException $e) {
        http_response_code(500);
        echo json_encode(['success' => false, 'message' => '数据库错误: ' . $e->getMessage()]);
    }
}
?>

2. 使用封装的数据处理类

<?php
class DataProcessor {
    
    public static function getJsonInput() {
        $input = json_decode(file_get_contents('php://input'), true);
        return is_array($input) ? $input : [];
    }
    
    public static function validateEmail($email) {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }
    
    public static function sanitizeString($string, $maxLength = 255) {
        $string = trim($string);
        $string = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
        return substr($string, 0, $maxLength);
    }
    
    public static function validateRequired($data, $fields) {
        $errors = [];
        foreach ($fields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 是必填字段";
            }
        }
        return $errors;
    }
}

// 使用示例
$input = DataProcessor::getJsonInput();

$requiredFields = ['username', 'email'];
$validationErrors = DataProcessor::validateRequired($input, $requiredFields);

if (!empty($validationErrors)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'errors' => $validationErrors]);
    exit;
}

// 清理数据
$cleanData = [
    'username' => DataProcessor::sanitizeString($input['username']),
    'email' => filter_var($input['email'], FILTER_SANITIZE_EMAIL),
];

if (!DataProcessor::validateEmail($cleanData['email'])) {
    echo json_encode(['success' => false, 'errors' => ['邮箱格式无效']]);
    exit;
}

// 然后执行数据库操作...
?>

3. 完整的邮件发送数据处理示例

<?php
// send-email.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
    // 获取并验证数据
    $input = json_decode(file_get_contents('php://input'), true) ?? [];
    
    $emailData = [
        'to' => filter_var($input['to'] ?? '', FILTER_SANITIZE_EMAIL),
        'subject' => htmlspecialchars($input['subject'] ?? '', ENT_QUOTES, 'UTF-8'),
        'content' => htmlspecialchars($input['content'] ?? '', ENT_QUOTES, 'UTF-8'),
        'created_at' => date('Y-m-d H:i:s')
    ];
    
    // 验证
    if (!filter_var($emailData['to'], FILTER_VALIDATE_EMAIL)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => '收件人邮箱格式错误']);
        exit;
    }
    
    if (empty($emailData['subject']) || empty($emailData['content'])) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => '邮件主题和内容不能为空']);
        exit;
    }
    
    try {
        // 先保存到数据库
        $pdo = new PDO('mysql:host=localhost;dbname=your_db;charset=utf8mb4', 'user', 'pass');
        
        $stmt = $pdo->prepare("INSERT INTO email_logs (to_email, subject, content, created_at) VALUES (:to, :subject, :content, :created_at)");
        $stmt->execute($emailData);
        
        // 然后发送邮件
        $mailSent = mail(
            $emailData['to'],
            $emailData['subject'], 
            $emailData['content'],
            "From: no-reply@yoursite.com\r\nContent-Type: text/html; charset=UTF-8"
        );
        
        if ($mailSent) {
            echo json_encode(['success' => true, 'message' => '邮件发送成功']);
        } else {
            echo json_encode(['success' => false, 'message' => '邮件发送失败']);
        }
        
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['success' => false, 'message' => '服务器错误: ' . $e->getMessage()]);
    }
}
?>

🛡️ 安全最佳实践总结

  1. 永远不要信任用户输入
  2. 始终进行数据验证和过滤
  3. 使用预处理语句防止SQL注入
  4. 创建清理后的数据数组再操作数据库
  5. 对输出进行编码防止XSS
  6. 使用合适的HTTP状态码

这样的做法既安全又易于维护,是专业的PHP开发标准。

posted @ 2025-10-18 12:58  充实地生活着  阅读(7)  评论(0)    收藏  举报