Функция cot_redirect в Cotonti
обеспечивает корректную обработку ошибок, проверяет целевой URL на безопасность, добавляет поддержку AJAX-состояния и выбирает способ редиректа в зависимости от настроек.
Разбор функции cot_redirect
1. Описание функции cot_redirect и её назначение:
Функция cot_redirect в Cotonti отвечает за безопасный и удобный способ перенаправления пользователя на указанный URL. Она обеспечивает корректную обработку ошибок, проверяет целевой URL на безопасность, добавляет поддержку AJAX-состояния и выбирает способ редиректа в зависимости от настроек.
2. Код штатной функции cot_redirect и пояснения:
/**
* Displays redirect page
*
* @param string $url Target URI
*/
function cot_redirect($url)
{
global $cfg, $env, $error_string, $sys;
if (cot_error_found() && $_SERVER['REQUEST_METHOD'] === 'POST') {
// Save the POST data
if (!empty($error_string)) {
// Message should not be lost
cot_error($error_string);
}
cot_import_buffer_save();
}
if (!cot_url_check($url)) {
// No redirects to foreign domains
if ($url == '/' || $url == $sys['site_uri']) {
$url = COT_ABSOLUTE_URL;
} else {
if ($url[0] === '/')
$url = mb_substr($url, 1);
$url = COT_ABSOLUTE_URL . $url;
}
}
if (defined('COT_AJAX') && COT_AJAX) {
// Save AJAX state, some browsers loose it after redirect (e.g. FireFox 3.6)
$sep = strpos($url, '?') === false ? '?' : '&';
$url .= $sep . '_ajax=1';
}
if (isset($env['status'])) {
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
header($protocol . ' ' . $env['status']);
}
if ($cfg['redirmode']) {
$output = $cfg['doctype'].<<<HTM
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="refresh" content="0; url=$url" />
<title>Redirecting...</title></head>
<body>Redirecting to <a href="$url">$url</a>
</body>
</html>
HTM;
header('Refresh: 0; URL='.$url);
echo $output;
exit;
}
else
{
header('Location: '.$url);
exit;
}
}
Сохранение данных POST-запроса при наличии ошибок:
if (cot_error_found() && $_SERVER['REQUEST_METHOD'] === 'POST') {
// Save the POST data
if (!empty($error_string)) {
// Message should not be lost
cot_error($error_string);
}
cot_import_buffer_save();
}
Пояснение:
Если при обработке POST-запроса были обнаружены ошибки (cot_error_found()), функция сохраняет данные POST-запроса и выводит сообщения об ошибках. Это позволяет вернуть пользователя на форму с сохранением введённых данных и выводом ошибок.
Функция cot_import_buffer_save() используется для сохранения данных формы в буфер, чтобы их можно было восстановить при повторном отображении.
Проверка целевого URL:
if (!cot_url_check($url)) {
// No redirects to foreign domains
if ($url == '/' || $url == $sys['site_uri']) {
$url = COT_ABSOLUTE_URL;
} else {
if ($url[0] === '/')
$url = mb_substr($url, 1);
$url = COT_ABSOLUTE_URL . $url;
}
}
Пояснение:
Для предотвращения редиректов на сторонние домены проверяется валидность URL через функцию cot_url_check($url).
Если URL — это корень сайта (/) или его базовый URI, он преобразуется в абсолютный адрес сайта.
Если путь начинается с /, символ удаляется, а затем URL преобразуется в абсолютный адрес с добавлением домена (COT_ABSOLUTE_URL).
Эта проверка предотвращает перенаправление на вредоносные внешние сайты.
Обработка AJAX-запросов:
if (defined('COT_AJAX') && COT_AJAX) {
// Save AJAX state, some browsers loose it after redirect (e.g. FireFox 3.6)
$sep = strpos($url, '?') === false ? '?' : '&';
$url .= $sep . '_ajax=1';
}
Пояснение:
Если редирект выполняется во время AJAX-запроса, к URL добавляется параметр _ajax=1, чтобы сохранить состояние AJAX. Это важно для корректной работы некоторых браузеров (например, Firefox 3.6), которые могут потерять информацию о типе запроса после редиректа.
Установка HTTP-статуса:
if (isset($env['status'])) {
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
header($protocol . ' ' . $env['status']);
}
Пояснение:
Если в массиве $env установлен статус HTTP, он отправляется в заголовке ответа. Это позволяет указать конкретный HTTP-статус, например, 302 Found или 301 Moved Permanently.
Режимы редиректа:
if ($cfg['redirmode']) {
$output = $cfg['doctype'].<<<HTM
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="refresh" content="0; url=$url" />
<title>Redirecting...</title></head>
<body>Redirecting to <a href="$url">$url</a>
</body>
</html>
HTM;
header('Refresh: 0; URL='.$url);
echo $output;
exit;
}
else
{
header('Location: '.$url);
exit;
}
Пояснение:
В зависимости от значения настройки $cfg['redirmode'] используются два режима редиректа:
Режим с использованием HTML-мета-тега <meta http-equiv="refresh">:
Генерируется HTML-документ с мета-тегом refresh, указывающим на целевой URL.
Включается дополнительный заголовок Refresh: 0, который немедленно перенаправляет на указанный адрес.
Этот режим используется для редиректов, когда требуется отобразить страницу с пояснением (например, "Redirecting...").
Обычный HTTP-редирект:
Выполняется через заголовок Location:, стандартный способ редиректа.
Обычно более быстрый и предпочтительный способ перенаправления.
3. Выводы:
Функция cot_redirect в Cotonti — это универсальный инструмент для обработки перенаправлений:
Она сохраняет данные POST-запросов в случае ошибок, чтобы пользователи не теряли данные.
Проверяет URL на безопасность, исключая перенаправления на сторонние домены.
Учитывает специфику AJAX-запросов, поддерживая их состояние после редиректа.
Поддерживает два режима редиректа: через мета-тег или стандартный HTTP-заголовок.
Эта функция — ключевой элемент, обеспечивающий безопасные и удобные переходы в приложениях Cotonti.
Разбор использования функции cot_redirect() в реальном примере №1:
1. Тема:
Функция cot_redirect() используется для перенаправления пользователя на страницу, если обнаруживается, что он пытается получить доступ к ресурсу через прямую ссылку (hotlinking), минуя стандартные пути сайта. Этот механизм защищает от несанкционированного доступа.
2. Участок кода и комментарии:
Формирование параметров для URL:
$urlParams = ['c' => $pag['page_cat']];
if (!empty($al)) {
$urlParams['al'] = $al;
} else {
$urlParams['id'] = $id;
}
$pag['page_pageurl'] = cot_url('page', $urlParams, '', true);
Пояснение:
Массив $urlParams формирует параметры для построения URL страницы.
Ключ 'c' указывает на категорию страницы ($pag['page_cat']).
Если переменная $al (альтернативный алиас) не пустая, она добавляется в параметры как 'al'. В противном случае в параметры добавляется идентификатор страницы 'id'.
На основе массива $urlParams формируется URL с помощью функции cot_url('page', $urlParams, '', true). Эта функция генерирует корректный и безопасный URL для модуля 'page' с учётом переданных параметров.
Сформированный URL сохраняется в $pag['page_pageurl'].
Пример результата:
Если:
Категория страницы: news. Алиас: пустой ($al = ''). Идентификатор страницы: 42. Результирующий URL будет: https://example.com/page?id=42&c=news.
Проверка на прямой доступ (hotlinking):
if (
isset($_SESSION['dl'])
&& $_SESSION['dl'] != $id
&& isset($_SESSION['cat'])
&& $_SESSION['cat'] != $pag['page_cat']
) {
cot_redirect($pag['page_pageurl']);
}
Пояснение:
Проверяется сессия пользователя, чтобы определить, не пытается ли он обойти правила доступа:
Существует ли идентификатор страницы в сессии ($_SESSION['dl']).
Совпадает ли текущий идентификатор страницы ($id) с сохранённым в сессии.
Существует ли категория страницы в сессии ($_SESSION['cat']).
Совпадает ли текущая категория страницы ($pag['page_cat']) с сохранённой в сессии.
Если хотя бы одна из этих проверок не проходит (то есть пользователь пытается получить доступ к странице, которой у него не должно быть), выполняется перенаправление на корректный URL страницы с помощью cot_redirect($pag['page_pageurl']).
3. Вывод:
В данном коде используется механизм защиты от hotlinking.
Функция cot_redirect() служит для перенаправления пользователя на корректный URL страницы в случае попытки обойти правила доступа.
Логика основана на проверке данных сессии: идентификатора страницы и категории.
Если данные сессии и текущие данные не совпадают, пользователь перенаправляется на корректный URL.
Это помогает избежать некорректного доступа, обеспечивая безопасность и контроль над доступом к контенту.
Примечание:
Если пользователь пытается "подменить" параметры в URL или перейти к ресурсу через внешнюю ссылку, защита автоматически перенаправляет его на легитимный адрес страницы.
Реальный пример №2 использования функции cot_redirect() в Cotonti
/** @see cot_user_authorize() */
$query = 'SELECT user_id,user_name, user_password, user_maingrp, user_banexpire, user_sid, user_sidtime, '
. 'user_passsalt, user_passfunc FROM ' . Cot::$db->users . ' WHERE ';
$sql = Cot::$db->query($query . $userSelectCondition, $userSelectParams);
/*
Checking if we got any entries with the current login conditions,
only may fail when user name has e-mail format or user is not registered,
added for compatibility, because disallowed using e-mail as login on registration
*/
if ($sql->rowCount() == 0) {
// If login has e-mail format, try to find it as user_name
$userSelectCondition2 = "user_password = " . Cot::$db->quote($rmdpass)
. " AND user_name = " . Cot::$db->quote($rusername);
// Query the database
$sql = Cot::$db->query($query . $userSelectCondition2);
}
$row = $sql->fetch();
if (!$row) {
Cot::$env['status'] = '401 Unauthorized';
cot_shield_update(7, "Log in");
cot_log('Log in failed, user: ' . $rusername, 'users', 'login', 'error');
/* === Hook === */
foreach (cot_getextplugins('users.auth.check.fail') as $pl) {
include $pl;
}
/* ===== */
cot_redirect(cot_url('message', 'msg=151', '', true));
}
Анализ использования функции cot_redirect() в данном коде
1. Тезис:
Функция cot_redirect() используется для перенаправления пользователя на страницу сообщения об ошибке в случае, если аутентификация завершилась неудачей. Этот механизм позволяет пользователю увидеть причину ошибки, а также предоставляет ему возможность повторить попытку входа.
2. Участок кода и комментарии:
Выполнение основного запроса для проверки данных пользователя:
$query = 'SELECT user_id, user_name, user_password, user_maingrp, user_banexpire, user_sid, user_sidtime, '
. 'user_passsalt, user_passfunc FROM ' . Cot::$db->users . ' WHERE ';
$sql = Cot::$db->query($query . $userSelectCondition, $userSelectParams);
Пояснение:
Формируется SQL-запрос, который извлекает из таблицы users основные данные о пользователе, такие как:
user_id (идентификатор пользователя),
user_name (имя пользователя),
user_password (хеш пароля),
user_maingrp (основная группа пользователя),
другие данные, связанные с авторизацией.
Условие выборки добавляется из переменной $userSelectCondition, а параметры для подстановки — из $userSelectParams. Это позволяет избежать SQL-инъекций.
Дополнительная проверка для имени пользователя в формате e-mail:
if ($sql->rowCount() == 0) {
$userSelectCondition2 = "user_password = " . Cot::$db->quote($rmdpass)
. " AND user_name = " . Cot::$db->quote($rusername);
$sql = Cot::$db->query($query . $userSelectCondition2);
}
Пояснение:
Если основной запрос не находит совпадений ($sql->rowCount() == 0), выполняется дополнительная проверка.
В этом случае предполагается, что пользователь ввёл e-mail вместо имени пользователя. Поэтому выполняется ещё один запрос, который сравнивает введённые данные:
user_password (пароль) и
user_name (имя, которое может быть e-mail).
Этот шаг добавляет гибкость в процесс авторизации, обеспечивая совместимость для пользователей.
Проверка результата запроса:
$row = $sql->fetch();
if (!$row) {
Cot::$env['status'] = '401 Unauthorized';
cot_shield_update(7, "Log in");
cot_log('Log in failed, user: ' . $rusername, 'users', 'login', 'error');
/* === Hook === */
foreach (cot_getextplugins('users.auth.check.fail') as $pl) {
include $pl;
}
/* ===== */
cot_redirect(cot_url('message', 'msg=151', '', true));
}
Пояснение:
Если запрос не возвращает данных ($row равно false), это означает, что введённые пользователем данные некорректны.
В этом случае:
Устанавливается статус HTTP-ответа 401 Unauthorized, чтобы сигнализировать о проблеме с авторизацией.
Вызывается функция cot_shield_update(), которая обновляет внутреннюю защиту сайта (например, может блокировать частые неудачные попытки входа).
Записывается лог с информацией о неудачной попытке входа с использованием имени пользователя $rusername.
Обработчики (хуки):
Код выполняет вызов всех подключаемых плагинов, которые зарегистрированы на событие 'users.auth.check.fail'. Эти хуки позволяют добавлять кастомную логику, связанную с обработкой ошибок авторизации.
Перенаправление:
Если аутентификация не удалась, пользователь перенаправляется на страницу с сообщением об ошибке:
cot_redirect(cot_url('message', 'msg=151', '', true));
Функция cot_url('message', 'msg=151', '', true) генерирует ссылку на страницу с кодом сообщения 151 (код сообщения, определённый в Cotonti для ошибки авторизации).
Функция cot_redirect() перенаправляет пользователя на эту страницу, используя заголовок Location.
3. Вывод:
Функция cot_redirect() играет ключевую роль в завершении процесса обработки неудачной авторизации.
Если авторизация провалилась (введённые имя пользователя или пароль некорректны), функция перенаправляет пользователя на страницу сообщения об ошибке.
Это позволяет пользователю увидеть причину неудачи и повторить попытку.
Использование хуков предоставляет возможность разработчикам расширять логику обработки ошибок.
В контексте безопасности перенаправление помогает предотвратить дальнейшую обработку неверных данных, минимизируя риски.
Комментарии (0)
Автор контента
Оффлайн
Administrator
Последняя авторизация: 05.07.2026 18:32
- Страница размещена: 23.01.2025 19:50
- Последнее обновление: 23.01.2025 20:03