PHP 怎么数据删除验证

wen PHP项目 1

本文目录导读:

PHP 怎么数据删除验证

  1. 基础权限验证
  2. 验证请求方法
  3. CSRF 令牌验证
  4. 数据存在性验证
  5. 关联数据验证
  6. 完整删除验证流程示例
  7. 注意事项
  8. 最佳实践建议
  9. 完整的前后端配合示例

在 PHP 中实现数据删除验证,通常涉及以下几个层面,我来详细介绍各种验证方法和最佳实践:

基础权限验证

用户身份验证

<?php
session_start();
// 验证用户是否登录
function checkLogin() {
    if (!isset($_SESSION['user_id'])) {
        die(json_encode(['error' => '未登录,请先登录']));
    }
    return $_SESSION['user_id'];
}
// 验证用户是否有删除权限
function checkPermission($user_id, $required_permission) {
    $pdo = getPDO();
    $stmt = $pdo->prepare("
        SELECT permission_name 
        FROM user_permissions 
        WHERE user_id = ? AND permission_name = ?
    ");
    $stmt->execute([$user_id, $required_permission]);
    return $stmt->fetch() !== false;
}

验证请求方法

<?php
// 确保只允许 POST 或 DELETE 请求
function validateRequestMethod($method = 'POST') {
    if ($_SERVER['REQUEST_METHOD'] !== $method) {
        http_response_code(405);
        die(json_encode(['error' => '请求方法不允许']));
    }
}
// 使用方法
validateRequestMethod('POST');
// 或
validateRequestMethod('DELETE');

CSRF 令牌验证

<?php
session_start();
// 生成 CSRF 令牌
function generateCSRFToken() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}
// 验证 CSRF 令牌
function verifyCSRFToken($token) {
    if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) {
        die(json_encode(['error' => 'CSRF 验证失败']));
    }
}
// 使用示例
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $csrf_token = $_POST['csrf_token'] ?? '';
    verifyCSRFToken($csrf_token);
}

数据存在性验证

<?php
// 验证要删除的数据是否存在
function validateDataExists($table, $id) {
    $pdo = getPDO();
    // 验证 ID 格式
    if (!filter_var($id, FILTER_VALIDATE_INT) || $id <= 0) {
        die(json_encode(['error' => '无效的 ID']));
    }
    // 验证数据是否存在
    $stmt = $pdo->prepare("SELECT id FROM {$table} WHERE id = ?");
    $stmt->execute([$id]);
    if (!$stmt->fetch()) {
        die(json_encode(['error' => '要删除的数据不存在']));
    }
    return $id;
}

关联数据验证

<?php
// 检查是否有关联数据
function checkRelatedData($check_array) {
    $pdo = getPDO();
    foreach ($check_array as $check) {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM {$check['table']} WHERE {$check['column']} = ?");
        $stmt->execute([$check['value']]);
        if ($stmt->fetchColumn() > 0) {
            die(json_encode([
                'error' => '无法删除,存在关联数据',
                'related_table' => $check['table']
            ]));
        }
    }
}
// 使用示例
$checks = [
    ['table' => 'orders', 'column' => 'user_id', 'value' => $user_id],
    ['table' => 'reviews', 'column' => 'user_id', 'value' => $user_id]
];
checkRelatedData($checks);

完整删除验证流程示例

<?php
class DataDeletionValidator {
    private $pdo;
    public function __construct($pdo) {
        $this->pdo = $pdo;
    }
    /**
     * 完整的删除验证流程
     */
    public function validate($table, $id, $user_id, $options = []) {
        // 1. 验证用户登录
        if (!$user_id) {
            throw new Exception('用户未登录', 401);
        }
        // 2. 验证请求方法
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            throw new Exception('请求方法不允许', 405);
        }
        // 3. 验证 CSRF
        if (isset($options['csrf']) && !verifyCSRFToken($_POST['csrf_token'])) {
            throw new Exception('CSRF 验证失败', 403);
        }
        // 4. 验证 ID 格式
        if (!is_numeric($id) || $id <= 0) {
            throw new Exception('无效的数据 ID', 400);
        }
        // 5. 验证数据存在性
        $stmt = $this->pdo->prepare("SELECT * FROM {$table} WHERE id = ?");
        $stmt->execute([$id]);
        $data = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$data) {
            throw new Exception('数据不存在', 404);
        }
        // 6. 验证数据所有权(如果是用户数据)
        if (isset($options['owner_column'])) {
            $owner_column = $options['owner_column'];
            if ($data[$owner_column] != $user_id) {
                throw new Exception('没有权限删除此数据', 403);
            }
        }
        // 7. 验证关联数据(避免外键约束冲突)
        if (isset($options['related'])) {
            foreach ($options['related'] as $related) {
                $stmt = $this->pdo->prepare(
                    "SELECT COUNT(*) FROM {$related['table']} WHERE {$related['column']} = ?"
                );
                $stmt->execute([$id]);
                if ($stmt->fetchColumn() > 0) {
                    throw new Exception(
                        "无法删除,存在关联数据在 {$related['table']} 表中", 
                        409
                    );
                }
            }
        }
        return true;
    }
}
// 使用示例
try {
    $validator = new DataDeletionValidator(getPDO());
    // 验证删除用户
    $validator->validate(
        'users', 
        $_POST['user_id'], 
        $_SESSION['user_id'],
        [
            'csrf' => true,
            'owner_column' => 'id', // 管理员可以删除任何用户,这里需要特殊处理
            // 或者可以检查是否为管理员
        ]
    );
    // 验证删除文章
    $validator->validate(
        'posts',
        $_POST['post_id'],
        $_SESSION['user_id'],
        [
            'csrf' => true,
            'owner_column' => 'author_id',
            'related' => [
                ['table' => 'comments', 'column' => 'post_id']
            ]
        ]
    );
    // 执行删除操作
    $stmt = $pdo->prepare("DELETE FROM posts WHERE id = ?");
    $stmt->execute([$_POST['post_id']]);
    echo json_encode(['success' => true, 'message' => '删除成功']);
} catch (Exception $e) {
    http_response_code($e->getCode());
    echo json_encode(['error' => $e->getMessage()]);
}

注意事项

软删除 vs 硬删除

<?php
// 软删除(推荐)
function softDelete($table, $id) {
    $stmt = $pdo->prepare(
        "UPDATE {$table} SET deleted_at = NOW(), deleted_by = ? WHERE id = ?"
    );
    $stmt->execute([$_SESSION['user_id'], $id]);
    return true;
}
// 硬删除
function hardDelete($table, $id) {
    $stmt = $pdo->prepare("DELETE FROM {$table} WHERE id = ?");
    $stmt->execute([$id]);
    return true;
}

操作日志记录

<?php
// 记录删除操作日志
function logDeletion($table, $id, $user_id, $details = '') {
    $stmt = $pdo->prepare("
        INSERT INTO deletion_logs (table_name, record_id, user_id, details, created_at) 
        VALUES (?, ?, ?, ?, NOW())
    ");
    $stmt->execute([$table, $id, $user_id, $details]);
}

最佳实践建议

  1. 总是验证:不要跳过任何验证步骤
  2. 使用参数化查询:防止 SQL 注入
  3. 实现软删除:比硬删除更安全
  4. 记录操作日志:便于审计和追踪
  5. 返回明确的错误信息:帮助用户理解问题
  6. 使用事务:确保数据一致性
  7. 考虑并发情况:防止并发删除问题

完整的前后端配合示例

<!-- 前端 HTML 表单 -->
<form id="deleteForm" method="POST">
    <input type="hidden" name="csrf_token" value="<?= generateCSRFToken() ?>">
    <input type="hidden" name="data_id" value="<?= $item_id ?>">
    <input type="hidden" name="confirm" value="1">
    <div class="delete-confirmation">
        <p>确定要删除这条记录吗?此操作不可恢复!</p>
        <button type="submit" class="btn-danger">确认删除</button>
        <button type="button" class="btn-cancel">取消</button>
    </div>
</form>
<script>
document.getElementById('deleteForm').addEventListener('submit', function(e) {
    e.preventDefault();
    if (!confirm('确定要删除吗?此操作不可恢复!')) {
        return;
    }
    fetch(this.action, {
        method: 'POST',
        body: new FormData(this)
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            alert('删除成功');
            window.location.href = '/list';
        } else {
            alert(data.error);
        }
    });
});
</script>

通过以上多层验证机制,可以确保 PHP 中的数据删除操作安全可靠,防止未授权访问和误操作。

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