Проверка прав доступа

В Vue Router проверка прав доступа реализуется через навигационные охранники (navigation guards), которые позволяют контролировать переходы между маршрутами. Основная цель — убедиться, что пользователь имеет необходимые права для просмотра определённого маршрута, и при необходимости перенаправить его на другой маршрут (например, страницу авторизации).


Типы охранников

  1. Глобальные охранники (global guards) Применяются ко всем маршрутам приложения. Существуют три основных метода:

    • router.beforeEach((to, from, next) => {}) — вызывается перед каждой навигацией. Позволяет проверять права доступа.
    • router.beforeResolve((to, from, next) => {}) — вызывается перед завершением навигации, после beforeEach и разрешения асинхронных компонентов.
    • router.afterEach((to, from) => {}) — вызывается после навигации, не предоставляет next() и служит только для побочных эффектов, например, логирования.
  2. Локальные охранники маршрутов (per-route guards) Определяются прямо в объекте маршрута:

    const routes = [
      {
        path: '/admin',
        component: AdminPanel,
        beforeEnter: (to, from, next) => {
          if (userIsAdmin()) {
            next();
          } else {
            next('/login');
          }
        }
      }
    ];
  3. Компонентные охранники (in-component guards) Используются внутри компонента:

    • beforeRouteEnter(to, from, next) — вызывается до создания компонента.
    • beforeRouteUpdate(to, from, next) — вызывается при обновлении маршрута, если используется тот же компонент.
    • beforeRouteLeave(to, from, next) — вызывается перед выходом с маршрута компонента.

Проверка авторизации

Для управления доступом обычно создаётся централизованная логика авторизации. Например, состояние пользователя хранится в Vuex, Pinia или через реактивное хранилище:

function isAuthenticated() {
  return store.state.user.isLoggedIn;
}

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isAuthenticated()) {
    next('/login');
  } else {
    next();
  }
});

Ключевой момент — метаданные маршрута (meta), которые позволяют маркировать маршруты, требующие авторизации:

const routes = [
  { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true } },
  { path: '/login', component: Login }
];

Проверка ролей и прав

В приложениях с разными уровнями доступа важна проверка ролей:

const routes = [
  { path: '/admin', component: AdminPanel, meta: { requiresRole: 'admin' } },
  { path: '/user', component: UserPanel, meta: { requiresRole: 'user' } }
];

router.beforeEach((to, from, next) => {
  const role = store.state.user.role;
  if (to.meta.requiresRole && to.meta.requiresRole !== role) {
    next('/forbidden');
  } else {
    next();
  }
});

Здесь meta.requiresRole задаёт необходимые права для маршрута, а глобальный beforeEach проверяет соответствие текущей роли пользователя.


Асинхронная проверка прав

Часто права доступа зависят от данных с сервера. Навигационные охранники поддерживают асинхронные операции:

router.beforeEach(async (to, from, next) => {
  if (to.meta.requiresAuth) {
    try {
      const user = await api.fetchCurrentUser();
      if (user && userHasAccess(user, to.meta)) {
        next();
      } else {
        next('/login');
      }
    } catch (error) {
      next('/login');
    }
  } else {
    next();
  }
});

Асинхронный beforeEach позволяет полностью контролировать переход, даже когда требуется загрузка данных перед маршрутом.


Рекомендации по организации проверки прав

  • Использовать метаданные: это централизует настройку маршрутов и упрощает проверку.
  • Разделять авторизацию и маршруты: логика проверки прав должна быть вынесена в отдельные функции или сервисы.
  • Комбинировать глобальные и локальные охранники: глобальные — для общих проверок (например, авторизация), локальные — для специфичных условий маршрута.
  • Обрабатывать редиректы корректно: при недостатке прав использовать next({ path: '/login', query: { redirect: to.fullPath } }) для возвращения на исходный маршрут после входа.

Примеры сложной логики доступа

Можно комбинировать несколько условий, например:

router.beforeEach((to, from, next) => {
  const user = store.state.user;
  
  if (!user.isLoggedIn && to.meta.requiresAuth) {
    next('/login');
  } else if (to.meta.requiresRole && !user.roles.includes(to.meta.requiresRole)) {
    next('/forbidden');
  } else {
    next();
  }
});

Такой подход позволяет гибко управлять доступом: учитываются как авторизация, так и роли, а также создаётся централизованная точка контроля навигации.


Использование динамических маршрутов

Vue Router позволяет проверять доступ даже для маршрутов с параметрами:

{
  path: '/projects/:id',
  component: ProjectDetail,
  meta: { requiresAuth: true },
  beforeEnter: (to, from, next) => {
    const projectId = to.params.id;
    if (userCanAccessProject(projectId)) {
      next();
    } else {
      next('/forbidden');
    }
  }
}

Динамический параметр :id передаётся в охранник и позволяет принимать решение о доступе индивидуально для каждого ресурса.


Использование Vue Router 4 с Composition API

С Composition API проверка прав может выполняться через useRouter и onBeforeRouteLeave / onBeforeRouteUpdate внутри setup:

import { useRouter, onBeforeRouteLeave } from 'vue-router';

setup() {
  const router = useRouter();

  onBeforeRouteLeave((to, from, next) => {
    if (!userHasAccess()) {
      next('/login');
    } else {
      next();
    }
  });
}

Это позволяет управлять правами непосредственно в компоненте, сохраняя реактивность состояния.


Проверка прав доступа в Vue Router объединяет метаданные маршрутов, глобальные и локальные охранники, асинхронные запросы и роли пользователя, обеспечивая гибкую и безопасную навигацию внутри приложения.