Files
conmed-authserver/local/modules/conmed.authserver/lib/securitytrait.php

75 lines
3.1 KiB
PHP
Executable File

<?php
namespace Conmed\Authserver;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Context;
use Bitrix\Main\Type\DateTime;
use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Loader;
trait SecurityTrait {
private static $allowedTables = [
'sso_codes' => '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();
}
}