在接收表单数据时进行合法性检验是确保应用安全的关键步骤。下面详细介绍如何在 PHP 类中实现全面的数据验证。
class UserValidator {
public function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
public function validateUrl($url) {
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
public function sanitizeInput($input) {
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
}
}
class InputValidator {
// 验证必填字段
public function required($value) {
return !empty(trim($value));
}
// 验证最小长度
public function minLength($value, $min) {
return strlen(trim($value)) >= $min;
}
// 验证最大长度
public function maxLength($value, $max) {
return strlen(trim($value)) <= $max;
}
// 验证数字范围
public function between($value, $min, $max) {
return $value >= $min && $value <= $max;
}
// 验证正则表达式
public function regex($value, $pattern) {
return preg_match($pattern, $value) === 1;
}
}
class FormValidator {
private $data;
private $errors = [];
private $rules = [];
public function __construct(array $data) {
$this->data = $data;
}
public function setRules(array $rules) {
$this->rules = $rules;
}
public function validate() {
foreach ($this->rules as $field => $ruleSet) {
$value = $this->data[$field] ?? null;
foreach ($ruleSet as $rule => $param) {
if ($rule === 'required' && !$this->validateRequired($value)) {
$this->addError($field, "$field 是必填字段");
break;
}
if ($rule === 'email' && !$this->validateEmail($value)) {
$this->addError($field, "$field 必须是有效的邮箱地址");
break;
}
if ($rule === 'min' && !$this->validateMinLength($value, $param)) {
$this->addError($field, "$field 至少需要 $param 个字符");
break;
}
if ($rule === 'max' && !$this->validateMaxLength($value, $param)) {
$this->addError($field, "$field 不能超过 $param 个字符");
break;
}
if ($rule === 'numeric' && !is_numeric($value)) {
$this->addError($field, "$field 必须是数字");
break;
}
// 可以添加更多验证规则...
}
}
return empty($this->errors);
}
private function validateRequired($value) {
return !empty(trim($value ?? ''));
}
private function validateEmail($value) {
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
private function validateMinLength($value, $min) {
return strlen(trim($value ?? '')) >= $min;
}
private function validateMaxLength($value, $max) {
return strlen(trim($value ?? '')) <= $max;
}
private function addError($field, $message) {
$this->errors[$field] = $message;
}
public function getErrors() {
return $this->errors;
}
public function getValidatedData() {
$cleanData = [];
foreach ($this->data as $key => $value) {
if (is_string($value)) {
$cleanData[$key] = htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
} else {
$cleanData[$key] = $value;
}
}
return $cleanData;
}
}
// 表单提交处理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$validator = new FormValidator($_POST);
// 设置验证规则
$validator->setRules([
'username' => [
'required' => true,
'min' => 4,
'max' => 20
],
'email' => [
'required' => true,
'email' => true
],
'password' => [
'required' => true,
'min' => 8
],
'age' => [
'numeric' => true
]
]);
if ($validator->validate()) {
// 获取经过验证和清理的数据
$cleanData = $validator->getValidatedData();
// 处理数据(如存入数据库)
// ...
echo "表单验证通过!";
} else {
// 显示错误信息
echo "验证错误:";
print_r($validator->getErrors());
}
}
class CustomValidator extends FormValidator {
// 验证手机号码
public function validatePhone($value) {
return preg_match('/^1[3-9]\d{9}$/', $value) === 1;
}
// 验证密码强度
public function validatePasswordStrength($value) {
return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/', $value) === 1;
}
}
class UserRegistrationValidator extends FormValidator {
private $db;
public function __construct(array $data, PDO $db) {
parent::__construct($data);
$this->db = $db;
}
// 验证用户名是否已存在
public function validateUsernameUnique($username) {
$stmt = $this->db->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
$stmt->execute([$username]);
return $stmt->fetchColumn() === 0;
}
// 验证邮箱是否已注册
public function validateEmailUnique($email) {
$stmt = $this->db->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
$stmt->execute([$email]);
return $stmt->fetchColumn() === 0;
}
}
输入过滤:
使用 htmlspecialchars()
防止 XSS 攻击
使用 trim()
去除多余空格
数据库安全:
永远使用预处理语句防止 SQL 注入
密码使用 password_hash()
存储
文件上传验证:
检查文件类型 (mime_content_type
)
检查文件大小
重命名上传的文件
CSRF 防护:
使用令牌验证表单来源
错误处理:
不要向用户显示详细的错误信息
记录错误日志
class UserRegistration {
private $db;
private $validator;
public function __construct(PDO $db) {
$this->db = $db;
}
public function register(array $data) {
$this->validator = new FormValidator($data);
$this->validator->setRules([
'username' => [
'required' => true,
'min' => 4,
'max' => 20
],
'email' => [
'required' => true,
'email' => true
],
'password' => [
'required' => true,
'min' => 8
],
'password_confirm' => [
'required' => true,
'matches' => 'password'
]
]);
if (!$this->validator->validate()) {
return ['success' => false, 'errors' => $this->validator->getErrors()];
}
$cleanData = $this->validator->getValidatedData();
// 检查用户名和邮箱是否已存在
if ($this->usernameExists($cleanData['username'])) {
return ['success' => false, 'errors' => ['username' => '用户名已存在']];
}
if ($this->emailExists($cleanData['email'])) {
return ['success' => false, 'errors' => ['email' => '邮箱已注册']];
}
// 创建用户
$hashedPassword = password_hash($cleanData['password'], PASSWORD_DEFAULT);
try {
$stmt = $this->db->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$stmt->execute([
$cleanData['username'],
$cleanData['email'],
$hashedPassword
]);
return ['success' => true, 'user_id' => $this->db->lastInsertId()];
} catch (PDOException $e) {
// 记录错误日志
error_log("注册失败: " . $e->getMessage());
return ['success' => false, 'errors' => ['system' => '注册失败,请稍后再试']];
}
}
private function usernameExists($username) {
$stmt = $this->db->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
$stmt->execute([$username]);
return $stmt->fetchColumn() > 0;
}
private function emailExists($email) {
$stmt = $this->db->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
$stmt->execute([$email]);
return $stmt->fetchColumn() > 0;
}
}
通过以上方法,你可以在 PHP 类中实现对表单数据的全面验证,确保数据的合法性和应用的安全性。根据项目需求,你可以扩展验证规则或创建更复杂的验证逻辑。