本文目录导读:

在 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]);
}
最佳实践建议
- 总是验证:不要跳过任何验证步骤
- 使用参数化查询:防止 SQL 注入
- 实现软删除:比硬删除更安全
- 记录操作日志:便于审计和追踪
- 返回明确的错误信息:帮助用户理解问题
- 使用事务:确保数据一致性
- 考虑并发情况:防止并发删除问题
完整的前后端配合示例
<!-- 前端 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 中的数据删除操作安全可靠,防止未授权访问和误操作。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播