diff --git a/src/Site/Controller/User.php b/src/Site/Controller/User.php index 16f73ad..def0d9f 100644 --- a/src/Site/Controller/User.php +++ b/src/Site/Controller/User.php @@ -18,10 +18,16 @@ class User { exit(); } - $doLogin = count($_POST) > 0; + $doLogin = $_SERVER['REQUEST_METHOD'] === 'POST'; $error = ''; if ($doLogin) { + if (!\verify_csrf_token($_POST['csrf_token'])) { + header('Location: /'); + exit(); + } + unset($_POST['csrf_token']); + $a = []; if (count($_POST) === 2) { $i = 0; @@ -91,6 +97,12 @@ class User { $nyuE = ''; if ($doRegister) { + if (!\verify_csrf_token($_POST['csrf_token'])) { + header('Location: /'); + exit(); + } + unset($_POST['csrf_token']); + $a = []; if (count($_POST) === 4) { $i = 0; diff --git a/src/Site/Lib/Auth.php b/src/Site/Lib/Auth.php index 1169834..7f5df25 100644 --- a/src/Site/Lib/Auth.php +++ b/src/Site/Lib/Auth.php @@ -51,30 +51,18 @@ class Auth { } $userData = $this->purgeOldTokens($userData); - $expire = 0; - $tokenExist = false; + $token = bin2hex(random_bytes(64)); + $expire = time() + $this->tokenDuration; + $newToken = [ + 'token' => $token, + 'ip' => $ip, + 'createDate' => time(), + 'expDate' => $expire, + 'lastDate' => time(), + 'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? '不明' + ]; - foreach ($userData->tokens as $t) { - if ($t->ip === $ip) { - $tokenExist = true; - break; - } - } - - if (!$tokenExist) { - $token = bin2hex(random_bytes(64)); - $expire = time() + $this->tokenDuration; - $newToken = [ - 'token' => $token, - 'ip' => $ip, - 'createDate' => time(), - 'expDate' => $expire, - 'lastDate' => time(), - 'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? '不明' - ]; - - $userData->tokens[] = $newToken; - } + $userData->tokens[] = $newToken; $path = $this->dataDir.$this->id.'.'.$userData->username.'.json'; $json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); @@ -83,20 +71,15 @@ class Auth { return \Result::error('エラー:ユーザーデータの保存に失敗。'); } - if (!$tokenExist) { - $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); - $domain = $_SERVER['SERVER_NAME']; - - if (!setcookie('kerozen', $token, [ - 'expires' => $expire, - 'path' => '/', - 'domain' => $domain, - 'secure' => $secure, - 'httponly' => true, - 'samesite' => 'Strict' - ])) { - return \Result::error('エラー:クッキーを設定に失敗。'); - } + if (!setcookie('kerozen', $token, [ + 'expires' => $expire, + 'path' => '/', + 'domain' => $_SERVER['SERVER_NAME'], + 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'), + 'httponly' => true, + 'samesite' => 'Strict' + ])) { + return \Result::error('エラー:クッキーを設定に失敗。'); } return \Result::success('ログイン成功'); @@ -111,8 +94,6 @@ class Auth { public function logout(?string $token = null): \Result { if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); - $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); - $domain = $_SERVER['SERVER_NAME']; $userData = $this->getUserData(); if (!$token) { @@ -124,8 +105,8 @@ class Auth { setcookie('kerozen', null, [ 'expires' => 0, 'path' => '/', - 'domain' => $domain, - 'secure' => $secure, + 'domain' => $_SERVER['SERVER_NAME'], + 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'), 'httponly' => true, 'samesite' => 'Strict' ]); diff --git a/util.php b/util.php index 05e5b48..d371950 100644 --- a/util.php +++ b/util.php @@ -160,6 +160,24 @@ if (AUTH_ENABLED) { return $color.$suffix; } + + function make_csrf_token(?bool $force = false): string { + if (null !== getcookie('csrf_token') && !$force) return getcookie('csrf_token'); + $token = bin2hex(random_bytes(32)); + setcookie('csrf_token', $token, [ + 'expires' => time() + 300, // 5分 + 'path' => '/', + 'domain' => $_SERVER['SERVER_NAME'], + 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'), + 'httponly' => true, + 'samesite' => 'Strict' + ]); + return $token; + } + + function verify_csrf_token(string $token): bool { + return hash_equals(getcookie('csrf_token'), $token); + } } function count_special_chars(string $str): int { diff --git a/view/login.maron b/view/login.maron index 4be3ba7..35860a5 100644 --- a/view/login.maron +++ b/view/login.maron @@ -28,7 +28,10 @@