'SsoCodes', 'sso_tokens' => 'SsoTokens', 'sso_audit' => 'SsoAudit', 'sso_security_log' => 'SsoSecurityLog' ]; public static function checkClient($clientId, $clientSecret = false, $redirectUri = false) { $rawList = Option::get("conmed.authserver", "client_list"); foreach(explode("\n", str_replace("\r", "", $rawList)) as $line) { $pair = explode(":", trim($line), 3); if($pair[0] === $clientId) { if($clientSecret !== false && !password_verify($clientSecret, $pair[1])) return false; if($redirectUri !== false) { $u = parse_url($redirectUri); if(!$u || empty($u['host'])) return false; $domain = str_replace(['https://','http://'], '', strtolower(trim($pair[2] ?? ""))); if(strtolower($u['host']) !== strtolower(trim($domain, " /"))) return false; } return true; } } return false; } public static function checkRateLimit($action = 'AUTH') { $ip = Context::getCurrent()->getRequest()->getRemoteAddress(); $dc = self::getHlEntity('sso_security_log'); $limit = DateTime::createFromTimestamp(time() - 300); $count = $dc::getCount(['=UF_IP' => $ip, '>UF_DATE' => $limit]); if ($count >= 20) { header('HTTP/1.1 429 Too Many Requests'); die(json_encode(['error' => 'Rate limit exceeded'])); } } public static function registerAttempt() { try { $dc = self::getHlEntity('sso_security_log'); $dc::add(['UF_IP' => Context::getCurrent()->getRequest()->getRemoteAddress(), 'UF_DATE' => new DateTime()]); } catch (\Exception $e) {} } public static function audit($event, $clientId, $userId = 0, $details = "") { try { $dc = self::getHlEntity('sso_audit'); $dc::add([ 'UF_EVENT' => $event, 'UF_CLIENT_ID' => $clientId, 'UF_USER_ID' => (int)$userId, 'UF_IP' => Context::getCurrent()->getRequest()->getRemoteAddress(), 'UF_DATE' => new DateTime(), 'UF_DETAILS' => substr($details, 0, 255) ]); } catch (\Exception $e) {} } public static function validatePassword($pass) { if (strlen($pass) < 6) return "Минимум 6 символов"; if (!preg_match("/[a-zA-Z]/", $pass) || !preg_match("/[0-9]/", $pass)) return "Пароль должен содержать буквы и цифры"; return true; } public static function getHlEntity($tableName) { if (!isset(self::$allowedTables[$tableName])) die("Access denied"); Loader::includeModule("highloadblock"); $hl = HighloadBlockTable::getList(['filter'=>['=TABLE_NAME'=>$tableName]])->fetch(); return HighloadBlockTable::compileEntity($hl)->getDataClass(); } }