Universal Router — это легковесная библиотека маршрутизации для JavaScript, обеспечивающая гибкий и декларативный способ обработки маршрутов. В контексте авторизации и аутентификации она предоставляет механизмы контроля доступа к различным маршрутам приложения, позволяя интегрировать защиту без сложных middleware.
Маршруты в Universal Router описываются в виде массива объектов, где
каждый объект содержит ключи path, action и
опционально дополнительные метаданные, например,
authRequired. Пример базовой структуры маршрута с
авторизацией:
const routes = [
{
path: '/',
action: () => 'Главная страница'
},
{
path: '/dashboard',
authRequired: true,
action: () => 'Панель управления'
},
{
path: '/login',
action: () => 'Страница входа'
}
];
Здесь authRequired используется для указания
необходимости авторизации перед доступом к маршруту. Universal Router
сам по себе не проверяет права доступа, но предоставляет возможность
реализовать логику проверки через функцию resolve.
resolveФункция resolve позволяет перехватывать маршруты и
выполнять дополнительные проверки перед вызовом action.
Типичная схема:
import UniversalRouter from 'universal-router';
const user = {
isAuthenticated: false
};
const router = new UniversalRouter(routes, {
resolve: (route, context, params) => {
if (route.authRequired && !user.isAuthenticated) {
return '/login'; // перенаправление на страницу входа
}
return route.action(context, params);
}
});
Ключевые моменты:
route — объект маршрута, который проходит
проверку.context — произвольные данные, передаваемые при вызове
router.resolve().params — параметры маршрута (например, динамические
сегменты /users/:id).Такой подход позволяет централизованно обрабатывать защиту маршрутов без необходимости дублирования кода в каждом маршруте.
Для более сложных сценариев, например, когда права доступа зависят от роли пользователя, можно расширить маршруты метаданными:
const routes = [
{
path: '/admin',
authRequired: true,
roles: ['admin'],
action: () => 'Административная панель'
}
];
const router = new UniversalRouter(routes, {
resolve: (route, context, params) => {
if (route.authRequired && !user.isAuthenticated) {
return '/login';
}
if (route.roles && !route.roles.includes(user.role)) {
return '/unauthorized';
}
return route.action(context, params);
}
});
В этом примере маршруты с roles ограничиваются
конкретными ролями пользователя, а Universal Router позволяет
обрабатывать их через единый resolve-колбэк.
Многие приложения используют асинхронные методы проверки авторизации,
например, через API-запросы. Universal Router полностью поддерживает
асинхронные action и resolve:
const router = new UniversalRouter(routes, {
resolve: async (route, context, params) => {
if (route.authRequired) {
const isAuth = await checkUserAuth(); // асинхронная проверка
if (!isAuth) return '/login';
}
return route.action(context, params);
}
});
Асинхронная проверка позволяет безопасно получать актуальное состояние пользователя перед рендером компонента.
Universal Router позволяет возвращать строку пути для перенаправления. Это особенно полезно для сценариев:
/login/unauthorized/forbiddenПример с вложенными маршрутами:
const routes = [
{
path: '/profile',
authRequired: true,
children: [
{ path: '', action: () => 'Мой профиль' },
{ path: '/edit', action: () => 'Редактировать профиль' }
]
}
];
Вложенные маршруты наследуют свойства родителя, включая
authRequired, что упрощает контроль доступа к целым секциям
приложения.
При использовании токенов или JWT проверка авторизации может включать декодирование токена и проверку его срока действия:
import jwtDecode from 'jwt-decode';
const router = new UniversalRouter(routes, {
resolve: (route, context, params) => {
const token = localStorage.getItem('token');
if (route.authRequired) {
if (!token) return '/login';
const payload = jwtDecode(token);
if (payload.exp * 1000 < Date.now()) return '/login';
}
return route.action(context, params);
}
});
Такой подход позволяет интегрировать маршрутизацию с существующей системой авторизации без лишних сложностей.
context в router.resolve может включать
текущего пользователя, настройки приложения и любые глобальные объекты.
Это упрощает доступ к данным при проверке прав:
const context = { user };
router.resolve('/dashboard', context)
.then(result => {
console.log(result);
});
Использование контекста позволяет сделать маршруты полностью независимыми от глобальных переменных и облегчает тестирование логики авторизации.
Чтобы после авторизации возвращать пользователя на исходную страницу, можно сохранять путь:
const router = new UniversalRouter(routes, {
resolve: (route, context, params) => {
if (route.authRequired && !context.user.isAuthenticated) {
return `/login?redirect=${encodeURIComponent(context.path)}`;
}
return route.action(context, params);
}
});
Это делает UX более удобным и обеспечивает корректное поведение при входе через сторонние провайдеры или после перезагрузки страницы.
Universal Router предоставляет гибкие инструменты для реализации
авторизации и аутентификации в JavaScript-приложениях. Ключевыми
концепциями являются использование метаданных маршрутов,
централизованная проверка через resolve, поддержка
асинхронной логики и интеграция с токенами или ролями пользователей.
Такой подход позволяет создавать безопасные и масштабируемые маршруты
без громоздких middleware и дополнительных библиотек.