Перейти к содержанию

Контроль доступа к маршрутам охранниками

📅 30.09.2026

Клиентские охранники нельзя считать единственным контролем доступа. Любой JavaScript, который выполняется в браузере, пользователь этого браузера может изменить. Авторизацию всегда проверяйте на сервере, в дополнение к охранникам на клиенте.

Охранники маршрута — функции, которые решают, может ли пользователь перейти на маршрут или покинуть его. Это контрольные точки доступа к конкретным маршрутам. Чаще всего ими закрывают аутентификацию и разграничение доступа.

Создание охранника маршрута

Охранник маршрута генерируют через Angular CLI:

1
ng generate guard CUSTOM_NAME

Команда предложит выбрать тип охранника маршрута и создаст файл CUSTOM_NAME-guard.ts.

Охранник можно написать и вручную: отдельный файл TypeScript в проекте Angular. Обычно в имени оставляют суффикс -guard.ts, чтобы файл было проще отличить от остальных.

Типы возврата охранника маршрута

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

Типы возврата Описание
boolean true разрешает переход, false блокирует его (см. примечание об охраннике CanMatch)
UrlTree или RedirectCommand Перенаправляет на другой маршрут вместо блокировки
Promise<T> или Observable<T> Маршрутизатор берёт первое выданное значение и отписывается

У CanMatch поведение другое: при возврате false Angular пробует остальные подходящие маршруты, а не блокирует навигацию целиком.

Типы охранников маршрута

В Angular четыре типа охранников маршрута, и у каждого своя задача:

Каждый охранник видит сервисы, предоставленные на уровне маршрута, и данные конкретного маршрута через аргумент route.

CanActivate

Охранник CanActivate решает, может ли пользователь открыть маршрут. Чаще всего его ставят на аутентификацию и авторизацию.

По умолчанию ему доступны такие аргументы:

  • route: ActivatedRouteSnapshot — сведения об активируемом маршруте
  • state: RouterStateSnapshot — текущее состояние маршрутизатора

Вернуть можно стандартные типы возврата охранника.

1
2
3
4
5
6
7
export const authGuard: CanActivateFn = (
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot,
) => {
  const authService = inject(AuthService);
  return authService.isAuthenticated();
};

Если пользователя нужно перенаправить, верните URLTree или RedirectCommand. Не возвращайте false и следом не вызывайте navigate программно.

Подробнее — в документации API CanActivateFn.

CanActivateChild

Охранник CanActivateChild решает, может ли пользователь открыть дочерние маршруты конкретного родителя. Им защищают целый раздел вложенных маршрутов. canActivateChild выполняется для всех дочерних маршрутов. Если у дочернего компонента есть свой дочерний компонент, canActivateChild выполнится по одному разу для обоих компонентов.

По умолчанию ему доступны такие аргументы:

  • childRoute: ActivatedRouteSnapshot — «будущий» снимок активируемого дочернего маршрута, то есть состояние, в которое маршрутизатор пытается перейти
  • state: RouterStateSnapshot — текущее состояние маршрутизатора

Вернуть можно стандартные типы возврата охранника.

1
2
3
4
5
6
7
export const adminChildGuard: CanActivateChildFn = (
  childRoute: ActivatedRouteSnapshot,
  state: RouterStateSnapshot,
) => {
  const authService = inject(AuthService);
  return authService.hasRole('admin');
};

Подробнее — в документации API CanActivateChildFn.

CanDeactivate

Охранник CanDeactivate решает, может ли пользователь покинуть маршрут. Частый сценарий — не дать уйти с формы, пока в ней есть несохранённые изменения.

По умолчанию ему доступны такие аргументы:

  • component: T — экземпляр деактивируемого компонента
  • currentRoute: ActivatedRouteSnapshot — сведения о текущем маршруте
  • currentState: RouterStateSnapshot — текущее состояние маршрутизатора
  • nextState: RouterStateSnapshot — следующее состояние маршрутизатора, куда идёт переход

Вернуть можно стандартные типы возврата охранника.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
export const unsavedChangesGuard: CanDeactivateFn<Form> = (
  component: Form,
  currentRoute: ActivatedRouteSnapshot,
  currentState: RouterStateSnapshot,
  nextState: RouterStateSnapshot,
) => {
  return component.hasUnsavedChanges()
    ? confirm('You have unsaved changes. Are you sure you want to leave?')
    : true;
};

Подробнее — в документации API CanDeactivateFn.

CanMatch

Охранник CanMatch решает, подходит ли маршрут при сопоставлении пути. Если маршрут отклонён, сопоставление переходит к другим подходящим маршрутам, а не останавливает навигацию целиком. Так делают флаги функций, A/B-тестирование и условную загрузку маршрутов.

По умолчанию ему доступны такие аргументы:

  • route: Route — проверяемая конфигурация маршрута
  • segments: UrlSegment[] — сегменты URL, которые ещё не разобраны при проверке родительских маршрутов
  • currentSnapshot: PartialMatchRouteSnapshot — снимок маршрута на текущем шаге сопоставления

Вернуть можно стандартные типы возврата охранника, но при false Angular пробует другие подходящие маршруты и не блокирует навигацию целиком.

1
2
3
4
5
6
7
8
export const featureToggleGuard: CanMatchFn = (
  route: Route,
  segments: UrlSegment[],
  currentSnapshot: PartialMatchRouteSnapshot,
) => {
  const featureService = inject(FeatureService);
  return featureService.isFeatureEnabled('newDashboard');
};

На один и тот же путь можно повесить разные компоненты.

routes.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const routes: Routes = [
  {
    path: 'dashboard',
    component: AdminDashboard,
    canMatch: [adminGuard],
  },
  {
    path: 'dashboard',
    component: UserDashboard,
    canMatch: [userGuard],
  },
];

Когда пользователь открывает /dashboard, берётся первый маршрут, чей охранник разрешил совпадение.

Подробнее — в документации API CanMatchFn.

Подключение охранников к маршрутам

Созданные охранники подключают в определениях маршрутов.

В конфигурации охранники задают массивом: на один маршрут можно повесить несколько. Они выполняются в том порядке, в каком стоят в массиве.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import {Routes} from '@angular/router';
import {authGuard} from './guards/auth.guard';
import {adminGuard} from './guards/admin.guard';
import {canDeactivateGuard} from './guards/can-deactivate.guard';
import {featureToggleGuard} from './guards/feature-toggle.guard';

const routes: Routes = [
  // Basic CanActivate - requires authentication
  {
    path: 'dashboard',
    component: Dashboard,
    canActivate: [authGuard],
  },

  // Multiple CanActivate guards - requires authentication AND admin role
  {
    path: 'admin',
    component: Admin,
    canActivate: [authGuard, adminGuard],
  },

  // CanActivate + CanDeactivate - protected route with unsaved changes check
  {
    path: 'profile',
    component: Profile,
    canActivate: [authGuard],
    canDeactivate: [canDeactivateGuard],
  },

  // CanActivateChild - protects all child routes
  {
    path: 'users', // /user - NOT protected
    canActivateChild: [authGuard],
    children: [
      // /users/list - PROTECTED
      {path: 'list', component: UserList},
      // /users/detail/:id - PROTECTED
      {path: 'detail/:id', component: UserDetail},
    ],
  },

  // CanMatch - conditionally matches route based on feature flag
  {
    path: 'beta-feature',
    component: BetaFeature,
    canMatch: [featureToggleGuard],
  },

  // Fallback route if beta feature is disabled
  {
    path: 'beta-feature',
    component: ComingSoon,
  },
];

Источник: https://angular.dev/guide/routing/route-guards

Комментарии