차량 모니터 mnt 인증 의존 제거

This commit is contained in:
seo committed 2026-07-28 22:36:04 +09:00
1 parent a1a9f29fcc
commit 36f5a30450
1 file changed
+84 -22
+84 -22
View File
@@ -17,6 +17,8 @@ define('DB_CHARSET', (string)($carDbConfig['charset'] ?? 'utf8mb4'));
const LOG_LIMIT = 300; const LOG_LIMIT = 300;
const CHART_LIMIT = 500; const CHART_LIMIT = 500;
const CAR_MONITOR_COOKIE = 'car_monitor_access';
const CAR_MONITOR_AUTH_TTL = 2592000;
const DATA_MONTHLY_INCLUDED_BYTES = 104857600; // 100MB const DATA_MONTHLY_INCLUDED_BYTES = 104857600; // 100MB
const DATA_BILLING_UNIT_BYTES = 512; // 0.5KB const DATA_BILLING_UNIT_BYTES = 512; // 0.5KB
const DATA_BILLING_UNIT_KRW = 0.011; const DATA_BILLING_UNIT_KRW = 0.011;
@@ -874,6 +876,72 @@ function json_response(array $payload, int $status = 200): void
exit; exit;
} }
function car_monitor_cookie_secret(): string
{
global $carSecretConfig;
$secret = (string)($carSecretConfig['monitor_auth']['secret'] ?? $carSecretConfig['auth_token'] ?? '');
if ($secret === '') {
throw new RuntimeException('Car monitor auth secret is missing.');
}
return $secret;
}
function car_monitor_cookie_options(int $expires): array
{
return [
'expires' => $expires,
'path' => '/car/',
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
'httponly' => true,
'samesite' => 'Strict',
];
}
function car_monitor_cookie_value(int $expires): string
{
$body = base64_encode(json_encode([
'exp' => $expires,
'iat' => time(),
], JSON_UNESCAPED_SLASHES));
$sig = hash_hmac('sha256', $body, car_monitor_cookie_secret());
return $body . '.' . $sig;
}
function car_monitor_issue_cookie(): void
{
$expires = time() + CAR_MONITOR_AUTH_TTL;
setcookie(CAR_MONITOR_COOKIE, car_monitor_cookie_value($expires), car_monitor_cookie_options($expires));
}
function car_monitor_has_cookie(): bool
{
$cookie = $_COOKIE[CAR_MONITOR_COOKIE] ?? '';
if (!is_string($cookie) || strpos($cookie, '.') === false) {
return false;
}
[$body, $sig] = explode('.', $cookie, 2);
$expected = hash_hmac('sha256', $body, car_monitor_cookie_secret());
if (!hash_equals($expected, $sig)) {
return false;
}
$decoded = base64_decode($body, true);
if ($decoded === false) {
return false;
}
$payload = json_decode($decoded, true);
if (!is_array($payload)) {
return false;
}
return (int)($payload['exp'] ?? 0) >= time();
}
function car_monitor_launcher_session(): array function car_monitor_launcher_session(): array
{ {
static $session = null; static $session = null;
@@ -886,11 +954,19 @@ function car_monitor_launcher_session(): array
if ($cookieHeader !== '') { if ($cookieHeader !== '') {
$remoteSession = car_monitor_launcher_api_request('GET', 'https://chaegeon.com/custom/launcher/api.php?session=1', null, $cookieHeader); $remoteSession = car_monitor_launcher_api_request('GET', 'https://chaegeon.com/custom/launcher/api.php?session=1', null, $cookieHeader);
if (is_array($remoteSession)) { if (is_array($remoteSession)) {
if (!empty($remoteSession['authenticated'])) {
car_monitor_issue_cookie();
}
$session = $remoteSession; $session = $remoteSession;
return $session; return $session;
} }
} }
if (car_monitor_has_cookie()) {
$session = ['authenticated' => true, 'admin' => false];
return $session;
}
$session = ['authenticated' => false, 'admin' => false]; $session = ['authenticated' => false, 'admin' => false];
return $session; return $session;
} }
@@ -978,7 +1054,7 @@ function car_monitor_require_access(bool $json = false): void
<main class="car-auth-page"> <main class="car-auth-page">
<div id="findMyShortcut"></div> <div id="findMyShortcut"></div>
</main> </main>
<script src="https://chaegeon.com/custom/common/js/auth-pin.js?v=<?php echo (int)(@filemtime('/mnt/synology-web/custom/common/js/auth-pin.js') ?: time()); ?>"></script> <script src="https://chaegeon.com/custom/common/js/auth-pin.js"></script>
<script> <script>
window.addEventListener('DOMContentLoaded', function () { window.addEventListener('DOMContentLoaded', function () {
window.CustomAuthPin && window.CustomAuthPin.render({ window.CustomAuthPin && window.CustomAuthPin.render({
@@ -1009,20 +1085,12 @@ function car_monitor_issue_pwa_cookie_if_requested(): void
return; return;
} }
$commonAuth = '/mnt/synology-web/custom/common/auth.php'; $cookieHeader = trim((string)($_SERVER['HTTP_COOKIE'] ?? ''));
if (!is_readable($commonAuth)) { $remoteSession = $cookieHeader !== ''
return; ? car_monitor_launcher_api_request('GET', 'https://chaegeon.com/custom/launcher/api.php?session=1', null, $cookieHeader)
} : null;
if (is_array($remoteSession) && !empty($remoteSession['authenticated'])) {
require_once $commonAuth; car_monitor_issue_cookie();
if (function_exists('custom_issue_auth_cookie')) {
$cookieHeader = trim((string)($_SERVER['HTTP_COOKIE'] ?? ''));
$remoteSession = $cookieHeader !== ''
? car_monitor_launcher_api_request('GET', 'https://chaegeon.com/custom/launcher/api.php?session=1', null, $cookieHeader)
: null;
if (is_array($remoteSession) && !empty($remoteSession['authenticated'])) {
custom_issue_auth_cookie(!empty($remoteSession['admin']));
}
} }
header('Location: /car/monitor.php', true, 302); header('Location: /car/monitor.php', true, 302);
@@ -1031,12 +1099,6 @@ function car_monitor_issue_pwa_cookie_if_requested(): void
function car_monitor_auth_api(): void function car_monitor_auth_api(): void
{ {
$commonAuth = '/mnt/synology-web/custom/common/auth.php';
if (!is_readable($commonAuth)) {
json_response(['result' => 'fail', 'message' => 'auth_module_missing'], 500);
}
require_once $commonAuth;
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['failMessages'])) { if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['failMessages'])) {
json_response(['failMessages' => ['비밀번호가 틀립니다.']]); json_response(['failMessages' => ['비밀번호가 틀립니다.']]);
} }
@@ -1056,7 +1118,7 @@ function car_monitor_auth_api(): void
'password' => $password, 'password' => $password,
]); ]);
if (is_array($remote) && ($remote['result'] ?? '') === 'ok') { if (is_array($remote) && ($remote['result'] ?? '') === 'ok') {
custom_issue_auth_cookie(false); car_monitor_issue_cookie();
json_response(['result' => 'ok']); json_response(['result' => 'ok']);
} }