Page.js — это небольшая библиотека для клиентской маршрутизации в
браузере. Она позволяет обрабатывать изменения URL без перезагрузки
страницы, создавая SPA-подобное поведение. Основной принцип работы
основан на подписке на события изменения window.location и
сопоставлении текущего пути с зарегистрированными маршрутами через
page(path, callback).
Маршруты могут содержать динамические параметры, которые автоматически извлекаются и передаются в колбэки:
page('/user/:id', ctx => {
console.log(ctx.params.id); // извлеченный id пользователя
});
Каждый маршрут получает объект ctx с ключевыми
свойствами: path, params,
querystring и hash.
Open Redirect возникает, когда приложение принимает внешние URL и автоматически перенаправляет на них без проверки. Это критическая уязвимость, так как злоумышленник может использовать её для фишинга или распространения вредоносных ссылок.
Пример уязвимого кода с Page.js:
page('/redirect', ctx => {
const target = ctx.querystring.split('=')[1];
window.location.href = target; // опасно!
});
В этом случае любой может передавать сторонний URL через
?url= и инициировать перенаправление на вредоносный
сайт.
Для предотвращения Open Redirect необходимо проверять передаваемые URL. Существует несколько подходов:
Создание массива допустимых путей внутри приложения:
const allowedPaths = ['/dashboard', '/profile', '/settings'];
page('/redirect', ctx => {
const target = ctx.querystring.split('=')[1];
if (allowedPaths.includes(target)) {
page(target);
} else {
page('/error');
}
});
Белый список гарантирует, что редирект произойдет только на заранее определённые маршруты внутри приложения.
Часто достаточно разрешать редирект только на пути без доменного имени:
page('/redirect', ctx => {
const target = ctx.querystring.split('=')[1];
if (target && target.startsWith('/')) {
page(target);
} else {
page('/error');
}
});
Это исключает возможность указания внешнего URL
(https://evil.com) и оставляет только внутренние
маршруты.
Если редирект зависит от динамических данных, лучше использовать идентификаторы, а не полный URL:
const redirectMap = {
home: '/',
dashboard: '/dashboard',
profile: '/profile'
};
page('/redirect/:target', ctx => {
const safePath = redirectMap[ctx.params.target];
if (safePath) {
page(safePath);
} else {
page('/');
}
});
В этом подходе пользователь никогда не передает полный URL, что полностью устраняет возможность Open Redirect.
Page.js позволяет работать с query-параметрами и хешами. Для безопасной маршрутизации их также необходимо проверять:
page('/redirect', ctx => {
const params = new URLSearchParams(ctx.querystring);
const target = params.get('page');
if (target && target.startsWith('/')) {
page(target);
} else {
page('/error');
}
});
Использование URLSearchParams упрощает обработку и
предотвращает ошибки при парсинге строки запроса.
Page.js поддерживает middleware-функции, которые вызываются перед основным колбэком маршрута. Это удобно для централизованной проверки редиректов:
function validateRedirect(ctx, next) {
const params = new URLSearchParams(ctx.querystring);
const target = params.get('page');
if (target && target.startsWith('/')) {
next();
} else {
page('/error');
}
}
page('/redirect', validateRedirect, ctx => {
const target = new URLSearchParams(ctx.querystring).get('page');
page(target);
});
Middleware позволяет масштабировать приложение и добавлять дополнительные проверки, не повторяя код для каждого маршрута.
Для усиления безопасности полезно вести логирование всех попыток редиректа на недопустимые URL:
page('*', ctx => {
if (ctx.path === '/redirect') {
const params = new URLSearchParams(ctx.querystring);
const target = params.get('page');
if (!target.startsWith('/')) {
console.warn(`Попытка недопустимого редиректа на: ${target}`);
}
}
});
Такой подход помогает обнаруживать потенциальные атаки и анализировать их источники.
При построении маршрутов важно комбинировать безопасные колбэки с шаблонами, которые не выводят пользовательский ввод напрямую в DOM без экранирования. Это снижает риск не только Open Redirect, но и XSS-уязвимостей.
Page.js предоставляет гибкие возможности маршрутизации, но безопасность редиректов требует строгого контроля входных данных. Белые списки, проверка внутренних путей и использование middleware являются ключевыми методами предотвращения Open Redirect, обеспечивая надежную работу SPA без риска фишинга и внешних атак.