From 9372cdc4bb2a00857e6c265f389f5bd15461ee72 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 21 Jul 2022 16:29:36 +0900 Subject: [PATCH] Add rx_login_status cookie for checking login status in mobile apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 회원정보 노출 없이 로그인 여부 및 서로 다른 회원을 구분할 수 있는 쿠키 - 인증이나 그 밖에 보안상 민감한 작업에는 사용하지 않음 - 모바일 앱에서 웹뷰의 로그인 상태가 앱이 기억하는 로그인 상태와 달라진 경우를 신속하게 파악할 수 있음 - 기타 API 클라이언트 등에서도 세션 상태 변화를 쉽게 감지할 수 있음 --- common/framework/session.php | 45 ++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/common/framework/session.php b/common/framework/session.php index 0e77131e9..0bcd47836 100644 --- a/common/framework/session.php +++ b/common/framework/session.php @@ -226,6 +226,9 @@ class Session } */ + // Check the login status cookie. + self::checkLoginStatusCookie(); + // Create or refresh the session if needed. if ($must_create) { @@ -292,6 +295,42 @@ class Session return false; } + /** + * Check the login status cookie. + * + * This cookie encodes information about whether the user is logged in, + * and helps client software distinguish between different users. + * + * @return void + */ + public static function checkLoginStatusCookie() + { + // Members are identified by a hash of member_srl. Guests are identified as 'none'. + if (isset($_SESSION['RHYMIX']) && $_SESSION['RHYMIX']['login']) + { + $data = sprintf('%s:%s:%d:%s', $_SERVER['HTTP_HOST'] ?? '', RX_BASEDIR, $_SESSION['RHYMIX']['login'], config('crypto.session_key')); + $value = base64_encode_urlsafe(substr(hash('sha256', $data, true), 0, 18)); + } + else + { + $value = 'none'; + } + + // If the cookie value is different from the current value, overwrite it. + if (!isset($_COOKIE['rx_login_status']) || $_COOKIE['rx_login_status'] !== $value) + { + list($lifetime, $refresh_interval, $domain, $path, $secure, $samesite) = self::_getParams(); + self::_setCookie('rx_login_status', $value, array( + 'expires' => 0, + 'path' => $path, + 'domain' => $domain, + 'secure' => $secure, + 'httponly' => true, + 'samesite' => $samesite, + )); + } + } + /** * Check if this session needs to be shared with another site with SSO. * @@ -539,9 +578,10 @@ class Session self::destroyAutologinKeys(); self::_unsetCookie(session_name(), $path, $domain); self::_unsetCookie('xe_logged', $path, $domain); + self::_unsetCookie('rx_login_status', $path, $domain); self::_unsetCookie('xeak', $path, $domain); self::_unsetCookie('sso', $path, $domain); - self::destroyCookiesFromConflictingDomains(array('xe_logged', 'xeak', 'sso')); + self::destroyCookiesFromConflictingDomains(array('xe_logged', 'rx_login_status', 'xeak', 'sso')); // Clear session data. $_SESSION = array(); @@ -590,6 +630,7 @@ class Session // Refresh the session keys. if ($refresh) { + self::checkLoginStatusCookie(); return self::refresh(); } else @@ -1156,7 +1197,7 @@ class Session } // Delete conflicting domain cookies. - self::destroyCookiesFromConflictingDomains(array(session_name(), 'rx_autologin', 'rx_sesskey1', 'rx_sesskey2')); + self::destroyCookiesFromConflictingDomains(array(session_name(), 'rx_autologin', 'rx_login_status', 'rx_sesskey1', 'rx_sesskey2')); return true; }