Files
sogoms/clients/prokov/api/core/Session.php
Pierre 7e27f87d6f Initial commit - SOGOMS v1.0.0
- sogoctl: supervisor avec health checks et restart auto
- sogoway: gateway HTTP, auth JWT, routing par hostname
- sogoms-db: microservice MariaDB avec pool par application
- Protocol IPC Unix socket JSON length-prefixed
- Config YAML multi-application (prokov)
- Deploy script pour container Alpine gw3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:09:00 +01:00

163 lines
4.2 KiB
PHP

<?php
/**
* Gestion des sessions en base de données
*/
declare(strict_types=1);
class Session
{
private static ?array $currentSession = null;
private static ?array $currentUser = null;
/**
* Récupérer l'IP réelle du client (derrière proxy)
*/
public static function getClientIp(): ?string
{
// Headers transmis par le proxy nginx
$headers = [
'HTTP_X_REAL_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_CLIENT_IP',
'REMOTE_ADDR',
];
foreach ($headers as $header) {
if (!empty($_SERVER[$header])) {
// X-Forwarded-For peut contenir plusieurs IPs (client, proxy1, proxy2...)
$ips = explode(',', $_SERVER[$header]);
$ip = trim($ips[0]);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
return null;
}
/**
* Créer une nouvelle session pour un utilisateur
*/
public static function create(int $userId, ?string $ipAddress = null, ?string $userAgent = null): string
{
$db = Database::getInstance();
$sessionId = bin2hex(random_bytes(64)); // 128 caractères
$expiresAt = date('Y-m-d H:i:s', time() + SESSION_LIFETIME);
$stmt = $db->prepare('
INSERT INTO sessions (id, user_id, ip_address, user_agent, expires_at)
VALUES (:id, :user_id, :ip_address, :user_agent, :expires_at)
');
$stmt->execute([
'id' => $sessionId,
'user_id' => $userId,
'ip_address' => $ipAddress ?? self::getClientIp(),
'user_agent' => $userAgent ?? $_SERVER['HTTP_USER_AGENT'] ?? null,
'expires_at' => $expiresAt,
]);
return $sessionId;
}
/**
* Valider une session et retourner l'utilisateur
*/
public static function validate(string $sessionId): ?array
{
if (self::$currentSession !== null && self::$currentSession['id'] === $sessionId) {
return self::$currentUser;
}
$db = Database::getInstance();
$stmt = $db->prepare('
SELECT s.*, u.id as user_id, u.email, u.name
FROM sessions s
JOIN users u ON s.user_id = u.id
WHERE s.id = :id AND s.expires_at > NOW()
');
$stmt->execute(['id' => $sessionId]);
$result = $stmt->fetch();
if (!$result) {
return null;
}
self::$currentSession = [
'id' => $result['id'],
'user_id' => $result['user_id'],
'expires_at' => $result['expires_at'],
];
self::$currentUser = [
'id' => $result['user_id'],
'email' => $result['email'],
'name' => $result['name'],
];
return self::$currentUser;
}
/**
* Détruire une session
*/
public static function destroy(string $sessionId): bool
{
$db = Database::getInstance();
$stmt = $db->prepare('DELETE FROM sessions WHERE id = :id');
$stmt->execute(['id' => $sessionId]);
self::$currentSession = null;
self::$currentUser = null;
return $stmt->rowCount() > 0;
}
/**
* Nettoyer les sessions expirées
*/
public static function cleanup(): int
{
$db = Database::getInstance();
$stmt = $db->prepare('DELETE FROM sessions WHERE expires_at < NOW()');
$stmt->execute();
return $stmt->rowCount();
}
/**
* Prolonger une session
*/
public static function extend(string $sessionId): bool
{
$db = Database::getInstance();
$expiresAt = date('Y-m-d H:i:s', time() + SESSION_LIFETIME);
$stmt = $db->prepare('
UPDATE sessions SET expires_at = :expires_at WHERE id = :id
');
$stmt->execute([
'id' => $sessionId,
'expires_at' => $expiresAt,
]);
return $stmt->rowCount() > 0;
}
/**
* Obtenir l'utilisateur courant (depuis le cache)
*/
public static function getCurrentUser(): ?array
{
return self::$currentUser;
}
}