При работе с Universal Router важно понимать, что
маршрутизация — это не только управление URL и обработка переходов, но и
потенциальная точка уязвимости приложения. Маршруты напрямую влияют на
доступ к ресурсам, поэтому некорректная конфигурация может привести к
утечке данных или обходу авторизации.
Ключевые аспекты безопасности:
/user/:id), нельзя использовать напрямую
в запросах к базе данных или API. Все параметры необходимо тщательно
проверять и экранировать.Universal Router предоставляет возможность использовать
асинхронные функции для обработки маршрутов, что удобно для проверки
прав доступа перед рендерингом страницы.
Пример:
import UniversalRouter from 'universal-router';
const routes = [
{
path: '/admin',
action: async (context) => {
if (!context.user || !context.user.isAdmin) {
throw new Error('Доступ запрещён');
}
return 'Административная панель';
}
},
{
path: '/profile/:id',
action: async ({ params, user }) => {
if (!user) throw new Error('Необходимо авторизоваться');
if (params.id !== user.id) throw new Error('Доступ к чужому профилю запрещён');
return `Профиль пользователя ${params.id}`;
}
}
];
const router = new UniversalRouter(routes);
В данном примере проверяется, что пользователь авторизован и имеет соответствующие права, прежде чем разрешить доступ к содержимому маршрута.
Маршруты должны корректно обрабатывать ошибки, чтобы пользователь не мог получить стек вызовов или внутреннюю информацию приложения. Рекомендуется использовать централизованный обработчик ошибок:
router.resolve('/admin').catch(error => {
if (error.message === 'Доступ запрещён') {
window.location.href = '/login';
} else {
console.error(error);
window.location.href = '/error';
}
});
Принципы безопасного редиректирования:
URL-параметры и query-параметры должны рассматриваться как потенциально небезопасные данные. Важно применять:
:id(\d+) предотвращает передачу строк вместо
чисел.Пример строгой проверки параметров:
{
path: '/user/:id(\\d+)',
action: ({ params }) => {
const userId = Number(params.id);
if (isNaN(userId)) throw new Error('Некорректный идентификатор пользователя');
return `Профиль пользователя ${userId}`;
}
}
Сложные вложенные маршруты повышают риск обхода логики безопасности.
В Universal Router можно использовать вложенные маршруты,
но каждый уровень должен проверять доступ:
{
path: '/dashboard',
children: [
{
path: 'settings',
action: ({ user }) => {
if (!user.isAdmin) throw new Error('Доступ запрещён');
return 'Настройки';
}
}
]
}
Для повышения безопасности рекомендуется логировать все попытки доступа к защищённым маршрутам. Это позволяет отслеживать потенциальные атаки и некорректные обращения:
router.resolve('/admin').catch(error => {
console.log(`Попытка доступа к /admin: ${error.message}`);
});
Хотя Universal Router не имеет встроенной системы
middleware, можно создать обёртку для маршрутов, которая будет проверять
авторизацию и параметры до выполнения основного действия:
function authWrapper(action) {
return async (context) => {
if (!context.user) throw new Error('Необходимо авторизоваться');
return action(context);
};
}
const routes = [
{ path: '/profile', action: authWrapper(({ user }) => `Профиль ${user.id}`) }
];
Такой подход позволяет централизованно управлять безопасностью без дублирования кода.
Эти практики помогут сделать маршрутизацию в
Universal Router безопасной и устойчивой к типовым атакам
на клиентские и серверные приложения.