feat: GTSIT 사이트 구축
This commit is contained in:
81
app/Auth/AdminAuth.php
Normal file
81
app/Auth/AdminAuth.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Auth;
|
||||
|
||||
use App\Database;
|
||||
use PDO;
|
||||
|
||||
final class AdminAuth
|
||||
{
|
||||
private PDO $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::connection();
|
||||
}
|
||||
|
||||
public function attempt(string $username, string $password): bool
|
||||
{
|
||||
$statement = $this->db->prepare(
|
||||
'SELECT id, username, display_name, password_hash, is_active, failed_attempts, locked_until
|
||||
FROM admins WHERE username = :username LIMIT 1'
|
||||
);
|
||||
$statement->execute(['username' => $username]);
|
||||
$admin = $statement->fetch();
|
||||
|
||||
if (!$admin) {
|
||||
password_verify($password, password_hash('invalid-login', PASSWORD_DEFAULT));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(bool) $admin['is_active']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($admin['locked_until'] && strtotime($admin['locked_until']) > time()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!password_verify($password, $admin['password_hash'])) {
|
||||
$failed = (int) $admin['failed_attempts'] + 1;
|
||||
$lockedUntil = $failed >= 5 ? date('Y-m-d H:i:s', time() + 900) : null;
|
||||
$update = $this->db->prepare('UPDATE admins SET failed_attempts = :failed, locked_until = :locked WHERE id = :id');
|
||||
$update->execute(['failed' => $failed >= 5 ? 0 : $failed, 'locked' => $lockedUntil, 'id' => $admin['id']]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$update = $this->db->prepare('UPDATE admins SET failed_attempts = 0, locked_until = NULL, last_login_at = NOW() WHERE id = :id');
|
||||
$update->execute(['id' => $admin['id']]);
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['admin'] = [
|
||||
'id' => (int) $admin['id'],
|
||||
'username' => $admin['username'],
|
||||
'display_name' => $admin['display_name'],
|
||||
'authenticated_at' => time(),
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function check(): bool
|
||||
{
|
||||
return isset($_SESSION['admin']['id'], $_SESSION['admin']['authenticated_at'])
|
||||
&& time() - (int) $_SESSION['admin']['authenticated_at'] < 7200;
|
||||
}
|
||||
|
||||
public static function requireLogin(): void
|
||||
{
|
||||
if (!self::check()) {
|
||||
unset($_SESSION['admin']);
|
||||
redirect('/admin/login');
|
||||
}
|
||||
$_SESSION['admin']['authenticated_at'] = time();
|
||||
}
|
||||
|
||||
public static function logout(): void
|
||||
{
|
||||
unset($_SESSION['admin']);
|
||||
session_regenerate_id(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user