Zarządzanie użytkownikami
Zarządzanie użytkownikami w XOOPS
Dział zatytułowany „Zarządzanie użytkownikami w XOOPS”System zarządzania użytkownikami XOOPS zapewnia kompletną strukturę obsługi rejestracji użytkowników, uwierzytelniania, zarządzania profilem i preferencji użytkownika. Dokument obejmuje strukturę obiektu użytkownika, przepływy rejestracji i praktyczne przykłady wdrażania.
Struktura obiektu użytkownika
Dział zatytułowany „Struktura obiektu użytkownika”Główny obiekt użytkownika w XOOPS to klasa XoopsUser, która zawiera wszystkie dane i metody użytkownika.
Schemat bazy danych
Dział zatytułowany „Schemat bazy danych”CREATE TABLE xoops_users ( uid INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, uname VARCHAR(25) NOT NULL UNIQUE, email VARCHAR(60) NOT NULL, pass VARCHAR(255) NOT NULL, pass_expired DATETIME DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, last_login DATETIME DEFAULT NULL, login_attempts INT(11) DEFAULT 0, user_avatar VARCHAR(255) NOT NULL DEFAULT 'blank.gif', user_regdate INT(11) NOT NULL DEFAULT 0, user_icq VARCHAR(15) NOT NULL DEFAULT '', user_from VARCHAR(100) NOT NULL DEFAULT '', user_sig TEXT, user_sig_smilies TINYINT(1) NOT NULL DEFAULT 1, user_viewemail TINYINT(1) NOT NULL DEFAULT 0, user_attachsig TINYINT(1) NOT NULL DEFAULT 0, user_theme VARCHAR(32) NOT NULL DEFAULT '', user_language VARCHAR(32) NOT NULL DEFAULT '', user_openid VARCHAR(255) NOT NULL DEFAULT '', user_notify_method TINYINT(1) NOT NULL DEFAULT 0, user_notify_interval INT(11) NOT NULL DEFAULT 0);Właściwości klasy XoopsUser
Dział zatytułowany „Właściwości klasy XoopsUser”class XoopsUser{ protected $uid; protected $uname; protected $email; protected $pass; protected $pass_expired; protected $created_at; protected $updated_at; protected $last_login; protected $login_attempts; protected $user_avatar; protected $user_regdate; protected $user_icq; protected $user_from; protected $user_sig; protected $user_sig_smilies; protected $user_viewemail; protected $user_attachsig; protected $user_theme; protected $user_language; protected $user_openid; protected $user_notify_method; protected $user_notify_interval;}Przepływ rejestracji użytkownika
Dział zatytułowany „Przepływ rejestracji użytkownika”Diagram sekwencji rejestracji
Dział zatytułowany „Diagram sekwencji rejestracji”sequenceDiagram participant User as Web User participant Browser participant Server as XOOPS Server participant DB as Database participant Email as Email Service
User->>Browser: Fill Registration Form Browser->>Server: POST /register
Server->>Server: Validate Input note over Server: Check username,<br/>email, password<br/>requirements
alt Validation Fails Server-->>Browser: Show Errors else Validation Passes Server->>Server: Hash Password Server->>DB: Insert User Record DB-->>Server: Success (uid)
Server->>Server: Generate Verification Token Server->>Email: Send Activation Email Email-->>User: Activation Link
Server-->>Browser: Registration Confirmation
User->>Email: Click Activation Link Email-->>Browser: Redirect to Activate URL Browser->>Server: GET /activate?token=xxx
Server->>DB: Mark User as Active DB-->>Server: Confirmed
Server-->>Browser: Account Activated Browser-->>User: Show Success Message endImplementacja rejestracji
Dział zatytułowany „Implementacja rejestracji”<?php/** * User Registration Handler */class RegistrationHandler{ private $userHandler; private $configHandler;
public function __construct() { $this->userHandler = xoops_getHandler('user'); $this->configHandler = xoops_getHandler('config'); }
/** * Validate registration input * * @param array $data Registration form data * @return array Validation errors, empty if valid */ public function validateInput(array $data): array { $errors = [];
// Username validation if (empty($data['uname'])) { $errors[] = 'Username is required'; } elseif (strlen($data['uname']) < 3) { $errors[] = 'Username must be at least 3 characters'; } elseif (!preg_match('/^[a-zA-Z0-9_-]+$/', $data['uname'])) { $errors[] = 'Username contains invalid characters'; } elseif ($this->userHandler->getUserByName($data['uname'])) { $errors[] = 'Username already exists'; }
// Email validation if (empty($data['email'])) { $errors[] = 'Email is required'; } elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $errors[] = 'Invalid email format'; } elseif ($this->userHandler->getUserByEmail($data['email'])) { $errors[] = 'Email already registered'; }
// Password validation if (empty($data['password'])) { $errors[] = 'Password is required'; } elseif (strlen($data['password']) < 8) { $errors[] = 'Password must be at least 8 characters'; } elseif ($data['password'] !== $data['password_confirm']) { $errors[] = 'Passwords do not match'; }
return $errors; }
/** * Register new user * * @param array $data Registration data * @return XoopsUser|false User object or false on failure */ public function registerUser(array $data) { // Validate input $errors = $this->validateInput($data); if (!empty($errors)) { return false; }
// Create user object $user = $this->userHandler->create(); $user->setVar('uname', $data['uname']); $user->setVar('email', $data['email']); $user->setVar('user_regdate', time());
// Hash password using bcrypt $hashedPassword = password_hash( $data['password'], PASSWORD_BCRYPT, ['cost' => 12] ); $user->setVar('pass', $hashedPassword);
// Set default preferences $user->setVar('user_theme', $this->configHandler->getConfig('default_theme')); $user->setVar('user_language', $this->configHandler->getConfig('default_language'));
// Save user if ($this->userHandler->insertUser($user)) { $uid = $user->getVar('uid');
// Generate verification token $token = bin2hex(random_bytes(32)); $this->saveVerificationToken($uid, $token);
// Send verification email $this->sendVerificationEmail($user, $token);
return $user; }
return false; }
/** * Save verification token * * @param int $uid User ID * @param string $token Verification token */ private function saveVerificationToken(int $uid, string $token): void { $tokenHandler = xoops_getHandler('usertoken'); $tokenHandler->saveToken($uid, $token, 'email_verification', 24); // 24 hours }
/** * Send verification email * * @param XoopsUser $user User object * @param string $token Verification token */ private function sendVerificationEmail(XoopsUser $user, string $token): void { global $xoopsConfig;
$siteUrl = $xoopsConfig['siteurl']; $activationUrl = $siteUrl . '/user.php?op=activate&token=' . $token;
$subject = 'Email Verification - ' . $xoopsConfig['sitename']; $body = "Hello " . $user->getVar('uname') . ",\n\n"; $body .= "Please click the link below to verify your email:\n"; $body .= $activationUrl . "\n\n"; $body .= "This link will expire in 24 hours.\n\n"; $body .= "Regards,\n" . $xoopsConfig['sitename'];
$mailHandler = xoops_getHandler('mail'); $mailHandler->send($user->getVar('email'), $subject, $body); }}Proces uwierzytelniania użytkownika
Dział zatytułowany „Proces uwierzytelniania użytkownika”Diagram przepływu uwierzytelniania
Dział zatytułowany „Diagram przepływu uwierzytelniania”graph TD A["Login Form"] --> B["Username/Email & Password"] B --> C{"Input Validation"} C -->|Invalid| D["Show Error"] C -->|Valid| E["Query User Database"] E --> F{"User Found?"} F -->|No| G["Invalid Credentials"] G --> H["Log Failed Attempt"] H --> I{"Max Attempts?"} I -->|Yes| J["Account Locked"] I -->|No| D F -->|Yes| K["Verify Password Hash"] K --> L{"Hash Match?"} L -->|No| H L -->|Yes| M["Check Account Status"] M --> N{"Account Active?"} N -->|No| O["Account Inactive/Suspended"] N -->|Yes| P["Create Session"] P --> Q["Store Session Token"] Q --> R{"Remember Me?"} R -->|Yes| S["Set Long-lived Cookie"] R -->|No| T["Set Session Cookie"] S --> U["Update Last Login"] T --> U U --> V["Redirect to Dashboard"]Implementacja uwierzytelniania
Dział zatytułowany „Implementacja uwierzytelniania”<?php/** * Authentication Handler */class AuthenticationHandler{ private $userHandler; private $maxLoginAttempts = 5; private $lockoutDuration = 900; // 15 minutes
public function __construct() { $this->userHandler = xoops_getHandler('user'); }
/** * Authenticate user by username/email and password * * @param string $username Username or email * @param string $password Plain text password * @param bool $rememberMe Remember login * @return XoopsUser|false Authenticated user or false */ public function authenticate( string $username, string $password, bool $rememberMe = false ) { // Check account lockout if ($this->isAccountLocked($username)) { throw new Exception('Account temporarily locked due to failed login attempts'); }
// Find user by username or email $user = $this->userHandler->getUserByName($username); if (!$user) { $user = $this->userHandler->getUserByEmail($username); }
if (!$user) { $this->recordFailedAttempt($username); return false; }
// Verify password if (!password_verify($password, $user->getVar('pass'))) { $this->recordFailedAttempt($username); return false; }
// Check account status if ($user->getVar('level') == 0) { throw new Exception('Account is inactive'); }
// Clear failed attempts $this->clearFailedAttempts($user->getVar('uid'));
// Update last login $user->setVar('last_login', date('Y-m-d H:i:s')); $this->userHandler->insertUser($user);
// Create session $this->createSession($user, $rememberMe);
return $user; }
/** * Create authenticated session * * @param XoopsUser $user User object * @param bool $rememberMe Enable persistent login */ private function createSession(XoopsUser $user, bool $rememberMe = false): void { // Generate session token $token = bin2hex(random_bytes(32));
$_SESSION['xoopsUserId'] = $user->getVar('uid'); $_SESSION['xoopsUserName'] = $user->getVar('uname'); $_SESSION['xoopsSessionToken'] = $token; $_SESSION['xoopsSessionCreated'] = time();
// Store token in database for validation $this->storeSessionToken($user->getVar('uid'), $token);
if ($rememberMe) { // Create persistent login cookie (14 days) $cookieToken = bin2hex(random_bytes(32)); setcookie( 'xoops_persistent_login', $cookieToken, time() + (14 * 24 * 60 * 60), '/', '', true, // HTTPS only true // HttpOnly );
// Store cookie token hash $this->storePersistentToken( $user->getVar('uid'), hash('sha256', $cookieToken) ); } }
/** * Record failed login attempt * * @param string $username Username or email */ private function recordFailedAttempt(string $username): void { $key = 'login_attempt_' . md5($username); $attempts = apcu_fetch($key) ?: 0; apcu_store($key, $attempts + 1, $this->lockoutDuration); }
/** * Check if account is locked * * @param string $username Username or email * @return bool True if locked */ private function isAccountLocked(string $username): bool { $key = 'login_attempt_' . md5($username); $attempts = apcu_fetch($key) ?: 0; return $attempts >= $this->maxLoginAttempts; }
/** * Clear failed attempts * * @param int $uid User ID */ private function clearFailedAttempts(int $uid): void { $user = $this->userHandler->getUser($uid); $user->setVar('login_attempts', 0); $this->userHandler->insertUser($user); }
/** * Store session token * * @param int $uid User ID * @param string $token Session token */ private function storeSessionToken(int $uid, string $token): void { // Store in database or cache $tokenData = [ 'uid' => $uid, 'token' => hash('sha256', $token), 'created' => time(), 'expires' => time() + (8 * 60 * 60) // 8 hours ];
$db = XoopsDatabaseFactory::getDatabaseConnection(); $db->query("INSERT INTO xoops_sessions (uid, token, created, expires) VALUES (?, ?, ?, ?)", array($uid, $tokenData['token'], $tokenData['created'], $tokenData['expires'])); }}Zarządzanie profilem
Dział zatytułowany „Zarządzanie profilem”Implementacja aktualizacji profilu
Dział zatytułowany „Implementacja aktualizacji profilu”<?php/** * User Profile Management */class ProfileManager{ private $userHandler; private $avatarHandler;
public function __construct() { $this->userHandler = xoops_getHandler('user'); $this->avatarHandler = xoops_getHandler('avatar'); }
/** * Update user profile * * @param int $uid User ID * @param array $data Profile data * @return bool Success status */ public function updateProfile(int $uid, array $data): bool { $user = $this->userHandler->getUser($uid); if (!$user) { return false; }
// Update profile fields if (isset($data['email'])) { // Verify email is unique (excluding current user) $existingUser = $this->userHandler->getUserByEmail($data['email']); if ($existingUser && $existingUser->getVar('uid') !== $uid) { throw new Exception('Email already in use'); } $user->setVar('email', $data['email']); }
if (isset($data['user_icq'])) { $user->setVar('user_icq', sanitize_text_field($data['user_icq'])); }
if (isset($data['user_from'])) { $user->setVar('user_from', sanitize_text_field($data['user_from'])); }
if (isset($data['user_sig'])) { $sig = $data['user_sig']; if (strlen($sig) > 500) { throw new Exception('Signature too long'); } $user->setVar('user_sig', $sig); }
if (isset($data['user_sig_smilies'])) { $user->setVar('user_sig_smilies', (int)$data['user_sig_smilies']); }
if (isset($data['user_viewemail'])) { $user->setVar('user_viewemail', (int)$data['user_viewemail']); }
if (isset($data['user_attachsig'])) { $user->setVar('user_attachsig', (int)$data['user_attachsig']); }
if (isset($data['user_theme'])) { $user->setVar('user_theme', $data['user_theme']); }
if (isset($data['user_language'])) { $user->setVar('user_language', $data['user_language']); }
return $this->userHandler->insertUser($user); }
/** * Change user password * * @param int $uid User ID * @param string $currentPassword Current password * @param string $newPassword New password * @return bool Success status */ public function changePassword( int $uid, string $currentPassword, string $newPassword ): bool { $user = $this->userHandler->getUser($uid); if (!$user) { return false; }
// Verify current password if (!password_verify($currentPassword, $user->getVar('pass'))) { throw new Exception('Current password is incorrect'); }
// Validate new password if (strlen($newPassword) < 8) { throw new Exception('New password must be at least 8 characters'); }
// Hash new password $hashedPassword = password_hash($newPassword, PASSWORD_BCRYPT, ['cost' => 12]); $user->setVar('pass', $hashedPassword);
return $this->userHandler->insertUser($user); }
/** * Get user profile data * * @param int $uid User ID * @return array Profile data */ public function getProfile(int $uid): array { $user = $this->userHandler->getUser($uid); if (!$user) { return []; }
return [ 'uid' => $user->getVar('uid'), 'uname' => $user->getVar('uname'), 'email' => $user->getVar('email'), 'user_regdate' => $user->getVar('user_regdate'), 'user_icq' => $user->getVar('user_icq'), 'user_from' => $user->getVar('user_from'), 'user_sig' => $user->getVar('user_sig'), 'user_viewemail' => $user->getVar('user_viewemail'), 'user_attachsig' => $user->getVar('user_attachsig'), 'user_theme' => $user->getVar('user_theme'), 'user_language' => $user->getVar('user_language'), 'last_login' => $user->getVar('last_login'), 'avatar' => $user->getVar('user_avatar') ]; }}Obsługa awatara
Dział zatytułowany „Obsługa awatara”Zarządzanie awatarem
Dział zatytułowany „Zarządzanie awatarem”<?php/** * User Avatar Handler */class AvatarHandler{ private $avatarPath = '/uploads/avatars/'; private $maxSize = 2097152; // 2MB private $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
/** * Upload user avatar * * @param int $uid User ID * @param array $file $_FILES array * @return string|false Avatar filename or false */ public function uploadAvatar(int $uid, array $file) { // Validate file if ($file['error'] !== UPLOAD_ERR_OK) { throw new Exception('File upload error: ' . $file['error']); }
if ($file['size'] > $this->maxSize) { throw new Exception('File too large (max 2MB)'); }
if (!in_array($file['type'], $this->allowedTypes)) { throw new Exception('Invalid file type'); }
// Verify MIME type $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($finfo, $file['tmp_name']); finfo_close($finfo);
if (!in_array($mimeType, $this->allowedTypes)) { throw new Exception('Invalid file content'); }
// Generate unique filename $extension = pathinfo($file['name'], PATHINFO_EXTENSION); $filename = 'avatar_' . $uid . '_' . time() . '.' . $extension;
// Create upload directory $uploadDir = XOOPS_ROOT_PATH . $this->avatarPath; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); }
$filepath = $uploadDir . $filename;
// Move uploaded file if (!move_uploaded_file($file['tmp_name'], $filepath)) { throw new Exception('Failed to move uploaded file'); }
// Resize image to standard size (150x150) $this->resizeImage($filepath, 150, 150);
// Update user avatar $userHandler = xoops_getHandler('user'); $user = $userHandler->getUser($uid);
// Delete old avatar if exists $oldAvatar = $user->getVar('user_avatar'); if ($oldAvatar && $oldAvatar !== 'blank.gif') { $oldPath = $uploadDir . $oldAvatar; if (file_exists($oldPath)) { unlink($oldPath); } }
// Save new avatar $user->setVar('user_avatar', $filename); $userHandler->insertUser($user);
return $filename; }
/** * Resize image to specified dimensions * * @param string $filepath Path to image file * @param int $width Target width * @param int $height Target height */ private function resizeImage(string $filepath, int $width, int $height): void { if (!extension_loaded('gd')) { return; // GD not available, skip resizing }
$image = imagecreatefromstring(file_get_contents($filepath)); if (!$image) { return; }
$resized = imagecreatetruecolor($width, $height);
// Preserve transparency for PNG and GIF $format = mime_content_type($filepath); if ($format === 'image/png' || $format === 'image/gif') { imagealphablending($resized, false); imagesavealpha($resized, true); }
imagecopyresampled( $resized, $image, 0, 0, 0, 0, $width, $height, imagesx($image), imagesy($image) );
// Save resized image $ext = pathinfo($filepath, PATHINFO_EXTENSION); if (strtolower($ext) === 'png') { imagepng($resized, $filepath, 9); } else { imagejpeg($resized, $filepath, 90); }
imagedestroy($image); imagedestroy($resized); }
/** * Delete user avatar * * @param int $uid User ID * @return bool Success status */ public function deleteAvatar(int $uid): bool { $userHandler = xoops_getHandler('user'); $user = $userHandler->getUser($uid);
if (!$user) { return false; }
$avatar = $user->getVar('user_avatar'); if ($avatar && $avatar !== 'blank.gif') { $filepath = XOOPS_ROOT_PATH . $this->avatarPath . $avatar; if (file_exists($filepath)) { unlink($filepath); } }
$user->setVar('user_avatar', 'blank.gif'); return $userHandler->insertUser($user); }}Preferencje użytkownika
Dział zatytułowany „Preferencje użytkownika”System preferencji
Dział zatytułowany „System preferencji”<?php/** * User Preferences Handler */class UserPreferencesHandler{ private $userHandler; private $prefixCache = 'user_pref_';
public function __construct() { $this->userHandler = xoops_getHandler('user'); }
/** * Get user preference * * @param int $uid User ID * @param string $prefKey Preference key * @param mixed $default Default value * @return mixed Preference value */ public function getPreference(int $uid, string $prefKey, $default = null) { // Try cache first $cacheKey = $this->prefixCache . $uid . '_' . $prefKey; $cached = apcu_fetch($cacheKey); if ($cached !== false) { return $cached; }
// Get from database $db = XoopsDatabaseFactory::getDatabaseConnection(); $result = $db->query( "SELECT pref_value FROM xoops_user_preferences WHERE uid = ? AND pref_key = ?", array($uid, $prefKey) );
if ($result && $db->getRowCount($result) > 0) { $row = $db->fetchArray($result); $value = unserialize($row['pref_value']); apcu_store($cacheKey, $value, 3600); // Cache for 1 hour return $value; }
return $default; }
/** * Set user preference * * @param int $uid User ID * @param string $prefKey Preference key * @param mixed $prefValue Preference value * @return bool Success status */ public function setPreference(int $uid, string $prefKey, $prefValue): bool { $db = XoopsDatabaseFactory::getDatabaseConnection();
// Check if preference exists $result = $db->query( "SELECT id FROM xoops_user_preferences WHERE uid = ? AND pref_key = ?", array($uid, $prefKey) );
$serialized = serialize($prefValue);
if ($db->getRowCount($result) > 0) { // Update existing preference $success = $db->query( "UPDATE xoops_user_preferences SET pref_value = ? WHERE uid = ? AND pref_key = ?", array($serialized, $uid, $prefKey) ); } else { // Insert new preference $success = $db->query( "INSERT INTO xoops_user_preferences (uid, pref_key, pref_value) VALUES (?, ?, ?)", array($uid, $prefKey, $serialized) ); }
if ($success) { // Clear cache $cacheKey = $this->prefixCache . $uid . '_' . $prefKey; apcu_delete($cacheKey); }
return (bool)$success; }
/** * Get all user preferences * * @param int $uid User ID * @return array All preferences */ public function getAllPreferences(int $uid): array { $db = XoopsDatabaseFactory::getDatabaseConnection(); $result = $db->query( "SELECT pref_key, pref_value FROM xoops_user_preferences WHERE uid = ?", array($uid) );
$prefs = []; while ($row = $db->fetchArray($result)) { $prefs[$row['pref_key']] = unserialize($row['pref_value']); }
return $prefs; }
/** * Delete user preference * * @param int $uid User ID * @param string $prefKey Preference key * @return bool Success status */ public function deletePreference(int $uid, string $prefKey): bool { $db = XoopsDatabaseFactory::getDatabaseConnection(); $success = $db->query( "DELETE FROM xoops_user_preferences WHERE uid = ? AND pref_key = ?", array($uid, $prefKey) );
if ($success) { $cacheKey = $this->prefixCache . $uid . '_' . $prefKey; apcu_delete($cacheKey); }
return (bool)$success; }}Przykłady operacji na użytkownikach
Dział zatytułowany „Przykłady operacji na użytkownikach”Typowe operacje na użytkownikach
Dział zatytułowany „Typowe operacje na użytkownikach”<?php/** * Common user operations examples */
// Get current logged-in user$xoopsUser = $GLOBALS['xoopsUser'];if ($xoopsUser instanceof XoopsUser) { $userId = $xoopsUser->getVar('uid'); $username = $xoopsUser->getVar('uname');}
// Get user by ID$userHandler = xoops_getHandler('user');$user = $userHandler->getUser(1);echo $user->getVar('uname');
// Get user by username$user = $userHandler->getUserByName('admin');if ($user) { echo $user->getVar('email');}
// Get user by email$user = $userHandler->getUserByEmail('user@example.com');
// Get all users in a group$users = $userHandler->getUsersByGroup(1);foreach ($users as $user) { echo $user->getVar('uname') . "\n";}
// Create new user$user = $userHandler->create();$user->setVar('uname', 'newuser');$user->setVar('email', 'newuser@example.com');$user->setVar('pass', password_hash('password', PASSWORD_BCRYPT));$user->setVar('user_regdate', time());
if ($userHandler->insertUser($user)) { echo "User created: " . $user->getVar('uid');}
// Delete user$userHandler->deleteUser(123);
// Get user object from ID$user = $userHandler->getUser(5);$profile = [ 'username' => $user->getVar('uname'), 'email' => $user->getVar('email'), 'regdate' => date('Y-m-d', $user->getVar('user_regdate')), 'avatar' => $user->getVar('user_avatar'),];Najlepsze praktyki bezpieczeństwa
Dział zatytułowany „Najlepsze praktyki bezpieczeństwa”Bezpieczeństwo hasła
Dział zatytułowany „Bezpieczeństwo hasła”- Zawsze używaj
password_hash()z algorytmemPASSWORD_BCRYPT - Użyj parametru cost równego 12 dla bcrypt
- Nigdy nie przechowuj haseł w postaci zwykłego tekstu
- Wdrażaj zasady wygaśnięcia hasła
- Wymagaj zmiany hasła dla skompromitowanych kont
Bezpieczeństwo sesji
Dział zatytułowany „Bezpieczeństwo sesji”<?php// Session configurationsession_set_cookie_params([ 'lifetime' => 0, // Session cookie (deleted on browser close) 'path' => '/', 'domain' => '', 'secure' => true, // HTTPS only 'httponly' => true, // Inaccessible to JavaScript 'samesite' => 'Strict' // CSRF protection]);
session_start();
// Regenerate session ID after loginsession_regenerate_id(true);
// Validate session tokenif (!isset($_SESSION['xoopsSessionToken'])) { session_destroy(); redirect('login');}Powiązane linki
Dział zatytułowany „Powiązane linki”- Group System.md
- Permission System.md
- Authentication.md
- ../../Security/Security-Guidelines.md
Znaczniki
Dział zatytułowany „Znaczniki”#users #registration #authentication #profiles #password-security #sessions