Απολύμανση εισροών
Ποτέ μην εμπιστεύεστε τα στοιχεία χρήστη. Πάντα να επικυρώνετε και να απολυμαίνετε όλα τα δεδομένα εισόδου πριν τα χρησιμοποιήσετε. Το XOOPS παρέχει την κλάση MyTextSanitizer για την εξυγίανση της εισαγωγής κειμένου και διάφορες βοηθητικές λειτουργίες για επικύρωση.
Σχετική τεκμηρίωση
Ενότητα με τίτλο «Σχετική τεκμηρίωση»- Security-Best-Practices - Περιεκτικός οδηγός ασφαλείας
- CSRF-Protection - Token system και XoopsSecurity class
- SQL-Injection-Prevention - Πρακτικές ασφαλείας βάσης δεδομένων
Ο χρυσός κανόνας
Ενότητα με τίτλο «Ο χρυσός κανόνας»Ποτέ μην εμπιστεύεστε τα δεδομένα χρήστη. Όλα τα δεδομένα από εξωτερικές πηγές πρέπει να είναι:
- Επικυρωμένο: Ελέγξτε ότι ταιριάζει με την αναμενόμενη μορφή και τύπο
- Sanitized: Αφαιρέστε ή αποφύγετε δυνητικά επικίνδυνους χαρακτήρες
- Escaped: Κατά την έξοδο, διαφυγή για το συγκεκριμένο περιβάλλον (HTML, JavaScript, SQL)
Τάξη MyTextSanitizer
Ενότητα με τίτλο «Τάξη MyTextSanitizer»Το XOOPS παρέχει την κλάση MyTextSanitizer (κοινώς ονομάζεται $myts) για εξυγίανση κειμένου.
# Λήψη της παρουσίας
Ενότητα με τίτλο «# Λήψη της παρουσίας»// Get the singleton instance$myts = MyTextSanitizer::getInstance();# Βασική εξυγίανση κειμένου
Ενότητα με τίτλο «# Βασική εξυγίανση κειμένου»$myts = MyTextSanitizer::getInstance();
// For plain text fields (no HTML allowed)$title = $myts->htmlSpecialChars($_POST['title']);
// This converts:// < to <// > to >// & to &// " to "// ' to '# Επεξεργασία περιεχομένου Textarea
Ενότητα με τίτλο «# Επεξεργασία περιεχομένου Textarea»Η μέθοδος displayTarea() παρέχει ολοκληρωμένη επεξεργασία περιοχής κειμένου:
$myts = MyTextSanitizer::getInstance();
$content = $myts->displayTarea( $_POST['content'], $allowhtml = 0, // 0 = No HTML allowed, 1 = HTML allowed $allowsmiley = 1, // 1 = Smilies enabled $allowxcode = 1, // 1 = XOOPS codes enabled (BBCode) $allowimages = 1, // 1 = Images allowed $allowlinebreak = 1 // 1 = Line breaks converted to <br>);# Κοινές Μέθοδοι Απολύμανσης
Ενότητα με τίτλο «# Κοινές Μέθοδοι Απολύμανσης»$myts = MyTextSanitizer::getInstance();
// HTML special characters escaping$safe_text = $myts->htmlSpecialChars($text);
// Strip slashes if magic quotes are on$text = $myts->stripSlashesGPC($text);
// Convert XOOPS codes (BBCode) to HTML$html = $myts->xoopsCodeDecode($text);
// Convert smileys to images$html = $myts->smiley($text);
// Make clickable links$html = $myts->makeClickable($text);
// Complete text processing for preview$preview = $myts->previewTarea($text, $allowhtml, $allowsmiley, $allowxcode);Επικύρωση εισόδου
Ενότητα με τίτλο «Επικύρωση εισόδου»# Επικύρωση ακέραιων τιμών
Ενότητα με τίτλο «# Επικύρωση ακέραιων τιμών»// Validate integer ID$id = isset($_REQUEST['id']) ? (int)$_REQUEST['id'] : 0;
if ($id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}
// Alternative with filter_var$id = filter_var($_REQUEST['id'] ?? 0, FILTER_VALIDATE_INT);if ($id === false || $id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}# Επικύρωση διευθύνσεων email
Ενότητα με τίτλο «# Επικύρωση διευθύνσεων email»$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$email) { redirect_header('form.php', 3, 'Invalid email address'); exit();}# Επικύρωση διευθύνσεων URL
Ενότητα με τίτλο «# Επικύρωση διευθύνσεων URL»$url = filter_var($_POST['url'], FILTER_VALIDATE_URL);
if (!$url) { redirect_header('form.php', 3, 'Invalid URL'); exit();}
// Additional check for allowed protocols$parsed = parse_url($url);$allowed_schemes = ['http', 'https'];if (!in_array($parsed['scheme'], $allowed_schemes)) { redirect_header('form.php', 3, 'Only HTTP and HTTPS URLs are allowed'); exit();}# Ημερομηνίες επικύρωσης
Ενότητα με τίτλο «# Ημερομηνίες επικύρωσης»$date = $_POST['date'] ?? '';
// Validate date format (YYYY-MM-DD)if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { redirect_header('form.php', 3, 'Invalid date format'); exit();}
// Validate actual date validity$parts = explode('-', $date);if (!checkdate($parts[1], $parts[2], $parts[0])) { redirect_header('form.php', 3, 'Invalid date'); exit();}# Επικύρωση ονομάτων αρχείων
Ενότητα με τίτλο «# Επικύρωση ονομάτων αρχείων»// Remove all characters except alphanumeric, underscore, and hyphen$filename = preg_replace('/[^a-zA-Z0-9_-]/', '', $_POST['filename']);
// Or use a whitelist approach$allowed_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';$filename = '';foreach (str_split($_POST['filename']) as $char) { if (strpos($allowed_chars, $char) !== false) { $filename .= $char; }}Χειρισμός διαφορετικών τύπων εισόδου
Ενότητα με τίτλο «Χειρισμός διαφορετικών τύπων εισόδου»# Εισαγωγή συμβολοσειράς
Ενότητα με τίτλο «# Εισαγωγή συμβολοσειράς»$myts = MyTextSanitizer::getInstance();
// Short text (titles, names)$title = $myts->htmlSpecialChars(trim($_POST['title']));
// Limit lengthif (strlen($title) > 255) { $title = substr($title, 0, 255);}
// Check for empty required fieldsif (empty($title)) { redirect_header('form.php', 3, 'Title is required'); exit();}# Αριθμητική είσοδος
Ενότητα με τίτλο «# Αριθμητική είσοδος»// Integer$count = (int)$_POST['count'];$count = max(0, min($count, 1000)); // Ensure range 0-1000
// Float$price = (float)$_POST['price'];$price = round($price, 2); // Round to 2 decimal places
// Validate rangeif ($price < 0 || $price > 99999.99) { redirect_header('form.php', 3, 'Invalid price'); exit();}# Boolean είσοδος
Ενότητα με τίτλο «# Boolean είσοδος»// Checkbox values$is_active = isset($_POST['is_active']) ? 1 : 0;
// Or with explicit value check$is_active = ($_POST['is_active'] ?? '') === '1' ? 1 : 0;# Εισαγωγή πίνακα
Ενότητα με τίτλο «# Εισαγωγή πίνακα»// Validate array input (e.g., multiple checkboxes)$selected_ids = [];if (isset($_POST['ids']) && is_array($_POST['ids'])) { foreach ($_POST['ids'] as $id) { $clean_id = (int)$id; if ($clean_id > 0) { $selected_ids[] = $clean_id; } }}# Select/Option Είσοδος
Ενότητα με τίτλο «# Select/Option Είσοδος»// Validate against allowed values$allowed_statuses = ['draft', 'published', 'archived'];$status = $_POST['status'] ?? '';
if (!in_array($status, $allowed_statuses)) { redirect_header('form.php', 3, 'Invalid status'); exit();}Αντικείμενο αίτησης (XMF)
Ενότητα με τίτλο «Αντικείμενο αίτησης (XMF)»Όταν χρησιμοποιείτε το XMF, η κλάση Request παρέχει πιο καθαρό χειρισμό εισόδου:
use Xmf\Request;
// Get integer$id = Request::getInt('id', 0);
// Get string$title = Request::getString('title', '');
// Get array$ids = Request::getArray('ids', []);
// Get with method specification$id = Request::getInt('id', 0, 'POST');$search = Request::getString('q', '', 'GET');
// Check request methodif (Request::getMethod() !== 'POST') { redirect_header('form.php', 3, 'Invalid request method'); exit();}Δημιουργία κλάσης επικύρωσης
Ενότητα με τίτλο «Δημιουργία κλάσης επικύρωσης»Για σύνθετες φόρμες, δημιουργήστε μια ειδική κλάση επικύρωσης:
<?phpnamespace XoopsModules\MyModule;
class Validator{ private $errors = [];
public function validateItem(array $data): bool { $this->errors = [];
// Title validation if (empty($data['title'])) { $this->errors['title'] = 'Title is required'; } elseif (strlen($data['title']) > 255) { $this->errors['title'] = 'Title must be 255 characters or less'; }
// Email validation if (!empty($data['email'])) { if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $this->errors['email'] = 'Invalid email format'; } }
// Status validation $allowed = ['draft', 'published']; if (!in_array($data['status'], $allowed)) { $this->errors['status'] = 'Invalid status'; }
return empty($this->errors); }
public function getErrors(): array { return $this->errors; }
public function getError(string $field): ?string { return $this->errors[$field] ?? null; }}Χρήση:
$validator = new Validator();$data = [ 'title' => $_POST['title'], 'email' => $_POST['email'], 'status' => $_POST['status'],];
if (!$validator->validateItem($data)) { $errors = $validator->getErrors(); // Display errors to user}Απολύμανση για αποθήκευση βάσεων δεδομένων
Ενότητα με τίτλο «Απολύμανση για αποθήκευση βάσεων δεδομένων»Κατά την αποθήκευση δεδομένων στη βάση δεδομένων:
$myts = MyTextSanitizer::getInstance();
// For storage (will be processed again on display)$title = $myts->addSlashes($_POST['title']);
// Better: Use prepared statements (see SQL Injection Prevention)$sql = "INSERT INTO " . $xoopsDB->prefix('mytable') . " (title) VALUES (?)";$result = $xoopsDB->query($sql, [$_POST['title']]);Απολύμανση για οθόνη
Ενότητα με τίτλο «Απολύμανση για οθόνη»Τα διαφορετικά περιβάλλοντα απαιτούν διαφορετική διαφυγή:
$myts = MyTextSanitizer::getInstance();
// HTML contextecho $myts->htmlSpecialChars($title);
// Within HTML attributesecho htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
// JavaScript contextecho json_encode($title);
// URL parameterecho urlencode($title);
// Full URLecho htmlspecialchars($url, ENT_QUOTES, 'UTF-8');Συνήθεις παγίδες
Ενότητα με τίτλο «Συνήθεις παγίδες»# Διπλή κωδικοποίηση
Ενότητα με τίτλο «# Διπλή κωδικοποίηση»Πρόβλημα: Τα δεδομένα κωδικοποιούνται πολλές φορές
// Wrong - double encoding$title = $myts->htmlSpecialChars($myts->htmlSpecialChars($_POST['title']));
// Right - encode once, at the appropriate time$title = $_POST['title']; // Store rawecho $myts->htmlSpecialChars($title); // Encode on output# Ασυνεπής κωδικοποίηση
Ενότητα με τίτλο «# Ασυνεπής κωδικοποίηση»Πρόβλημα: Ορισμένες έξοδοι είναι κωδικοποιημένες, άλλες όχι
Λύση: Να χρησιμοποιείτε πάντα μια συνεπή προσέγγιση, κατά προτίμηση κωδικοποιώντας στην έξοδο:
// Template assignment$GLOBALS['xoopsTpl']->assign('title', htmlspecialchars($title, ENT_QUOTES, 'UTF-8'));# Λείπει η επικύρωση
Ενότητα με τίτλο «# Λείπει η επικύρωση»Πρόβλημα: Απολύμανση μόνο χωρίς επικύρωση
Λύση: Πάντα να επικυρώνετε πρώτα και μετά να απολυμαίνετε:
// First validateif (!preg_match('/^[a-z0-9_]+$/', $_POST['username'])) { redirect_header('form.php', 3, 'Username contains invalid characters'); exit();}
// Then sanitize for storage/display$username = $myts->htmlSpecialChars($_POST['username']);Σύνοψη βέλτιστων πρακτικών
Ενότητα με τίτλο «Σύνοψη βέλτιστων πρακτικών»- Χρησιμοποιήστε το MyTextSanitizer για επεξεργασία περιεχομένου κειμένου
- Χρησιμοποιήστε filter_var() για επικύρωση συγκεκριμένης μορφής
- Χρησιμοποιήστε τύπο χύτευσης για αριθμητικές τιμές
- Λίστα λευκών επιτρεπόμενων τιμών για επιλεγμένες εισόδους
- Επικυρώστε πριν την απολύμανση
- Escape στην έξοδο, όχι στην είσοδο
- Χρησιμοποιήστε έτοιμες δηλώσεις για ερωτήματα βάσης δεδομένων
- Δημιουργήστε κλάσεις επικύρωσης για σύνθετες φόρμες
- Μην εμπιστεύεστε ποτέ την επικύρωση από την πλευρά του πελάτη - επικυρώνετε πάντα από την πλευρά του διακομιστή