Разница между canLoad и canActivate в Angular?

101

В чем разница между canLoadи canActivate?

export interface Route {
  path?: string;
  pathMatch?: string;
  matcher?: UrlMatcher;
  component?: Type<any>;
  redirectTo?: string;
  outlet?: string;
  canActivate?: any[];
  canActivateChild?: any[];
  canDeactivate?: any[];
  canLoad?: any[];
  data?: Data;
  resolve?: ResolveData;
  children?: Routes;
  loadChildren?: LoadChildren;
}

Когда мне следует какой из них?

Йоав Шнидерман
источник

Ответы:

100

canActivate используется для предотвращения доступа неавторизованных пользователей к определенным маршрутам. См. Документы для получения дополнительной информации.

canLoad используется для предотвращения ленивой загрузки целых модулей приложением, если пользователь не авторизован для этого.

См. Документы и пример ниже для получения дополнительной информации.

{
    path: 'admin',
    loadChildren: 'app/admin/admin.module#AdminModule',
    canLoad: [AuthGuard]
},

С этим кодом код для AdminModule будет загружен в приложение только в случае возврата AuthGuard true.

Если пользователь не авторизован для доступа к этому маршруту, и мы использовали только canActivateохрану, AdminModuleфайл будет загружен, даже если пользователь не сможет получить доступ к этому маршруту.

Фредрик Лундин
источник
6
Если я воспользуюсь canActivateописанным выше сценарием, какая будет разница?
k11k2 06
3
canActiveБудет загружен @ k11k2 с модулем (F12> Источники - в хроме). Там вы можете увидеть файлы .js. С canLoadэтими модулями (файлы .js) не загружаются :) Посмотрите мой ответ выше, где я объяснил это лучше
DiPix
23
Как насчет сценария, когда администратор вошел в систему, поэтому модуль администратора был загружен через, canLoadвозвращает true, а затем выходит из приложения. Теперь, когда пользователь без прав администратора входит в систему в том же браузере, как это работает? Был ли удален загруженный модуль из кеша?
Keerthivasan
2
@Keerthivasan ничто не заставляет удалить ранее загруженный фрагмент ленивого AdminModule, когда пользователь вышел из системы и снова войдет в систему с другой учетной записью, у которой недостаточно прав для загрузки AdminModule. Однако вы все равно не получите доступа .. кроме загруженного кэшированного модуля. Я не думаю, что это реальная проблема безопасности, поскольку обычно одно устройство - это один реальный пользователь
hastrb
1
@ sgClaudia98 можно использовать и то, и другое, но есть строгий порядок исполнения охранников. вот почему в вашем случае не имеет значения то, что я сказал немного раньше. Думаю, я вложил очень подробное объяснение в свой первый комментарий. Это было бы довольно странно, если бы в настоящее время есть одно устройство, и администратор / не администратор входит в систему один за другим.
hastrb
36
  • CanActivate - решает, можно ли активировать маршрут, эта защита может быть не лучшим способом для функциональных модулей, которые загружаются лениво, поскольку эта защита всегда будет загружать модуль в память, даже если охрана вернула false, что означает, что пользователь не авторизован для доступа маршрут.
  • CanLoad - определяет, можно ли лениво загружать модуль, контролирует, можно ли загрузить маршрут. Это становится полезным для функциональных модулей, которые загружаются лениво. Они даже не загрузятся, если охранник вернет false.

Это тест, который я провел на обоих охранниках с ленивым загруженным функциональным модулем:

1. Тест CanActivate Guard

Внизу страницы «Сеть» вы заметите, что он сделал 24 запроса размером 9,5 МБ, завершил передачу за 3,34 секунды и полную загрузку за 3,47 секунды.

Тест CanActivate Guard на функциональном модуле с отложенной загрузкой

1. Тест CanLoad Guard

здесь вы увидите большую разницу, когда мы использовали CanLoad Guard, поскольку браузер сделал всего 18 запросов размером 9,2 МБ, передал завершение за 2,64 секунды и полную загрузку за 2,59 секунды.

Тест CanLoad Guard на функциональном модуле с отложенной загрузкой

CanLoad Guard никогда не загружает данные модуля, если пользователь не авторизован, и это дает вам больше производительности, поскольку время загрузки уменьшилось почти на 1 секунду, а это огромное время для загрузки веб-страниц, без сомнения, это зависит от размера модуля.

Совет: если вы хотите провести тест в своем проекте, убедитесь, что Disable Cacheфлажок на вкладке сети установлен, он отмечен на первом изображении

Махмуд Фаузи
источник
3
Чтобы не запутать кого-то .. 403 - это Forbbiden, а не Unauthorized, то есть 401.
hastrb
20

Что касается вопроса из комментариев в другом сообщении «Если я использую canActivate в приведенном выше сценарии, какая будет разница?»

Собственно для пользователя разницы не будет, он не получит доступа к странице в обоих случаях. Хотя есть одно скрытое отличие . Если вы нажмете F12 и перейдете в Источники (в Chrome), где находятся файлы для загрузки. Тогда вы увидите, что в случае с canActive был загружен файл с кодом ( chunk.js ). Даже если у вас нет доступа к странице. введите описание изображения здесь

Но в случае с canLoad там не будет chunk.js файл с исходным кодом.

введите описание изображения здесь

Как видите, это действительно сильно влияет на безопасность.

И, конечно же, не забывайте, что canLoad можно использовать только для модулей LazyLoaded .

DiPix
источник
3
Невозможно увидеть какой-либо фрагмент модуля отложенной загрузки на вкладке сети, но маршруты работают должным образом. Как я могу подтвердить загрузку модулей по запросу или нет?
k11k2
@ k11k2, если вы хотите увидеть, частью какого файла является модуль, просто добавьте debugger;оператор в конструктор для одного из компонентов этого модуля. Затем вы можете увидеть, был ли он загружен как отдельный блок или включен в такой модуль, как main. Если у вас есть ссылки на компоненты в ленивом модуле, которые не изолированы от этого модуля, он все равно может быть загружен. Если вы видите это, это говорит о том, что вы фильтруете что-то другое, кроме файлов JS, или вам нужно разбить свой ленивый модуль на общие и «действительно ленивые» части.
Simon_Weaver 02
@ k11k2 Думаю, ваш "модуль ленивой загрузки" не загружается лениво. Убедитесь, что вы использовали loadChildrenсвойство как часть пути к вашему ленивому модулю.
hastrb
16

canActivate используется для предотвращения несанкционированного доступа

canLoad используется для предотвращения всего модуля приложения

Пример canActivate :

{ path: 'product',canActivate:[RouteGaurd], component : ProductComponent }

Пример canLoad :

{ path: 'user' , canLoad: [AuthenticGuard], loadChildren : './user/user.module#UserModule' }
Сагар Джадхав
источник
Будущим читателям пример canActive не ленив, а вот canLoad ... из-за наличия loadChildren. Более того, последняя версия angular - это ..loadChildren: () => import('./user/user.module').then(m => m.UserModule)
hastrb
Очень простое объяснение, понравилось :)
KTM
16

CanLoad Guard предотвращает загрузку загруженного модуля ленивых. Обычно мы используем эту защиту, когда мы не хотим, чтобы неавторизованный пользователь переходил к любому из маршрутов модуля, а также останавливался, а затем даже видел исходный код модуля.

Angular предоставляет canActivate Guard, который предотвращает несанкционированный доступ к маршруту. Но это не мешает загрузке модуля. Пользователь может использовать консоль разработчика Chrome для просмотра исходного кода. CanLoad Guard предотвращает загрузку модуля.

Фактически, CanLoad защищает загружаемый модуль, но после загрузки модуля CanLoad guard ничего не сделает. Предположим, мы защитили загрузку модуля с помощью CanLoad guard для неаутентифицированного пользователя. Когда пользователь вошел в систему, этот модуль можно будет загрузить, и мы сможем перемещаться по дочерним путям, настроенным этим модулем. Но когда пользователь выйдет из системы, он по-прежнему сможет перемещаться по этим дочерним путям, потому что модуль уже загружен. В этом случае, если мы хотим защитить дочерние пути от неавторизованных пользователей, нам также необходимо использовать CanActivate guard.

Используйте CanLoad перед загрузкой AdminModule:

  {
        path: 'admin',
        loadChildren: 'app/admin/admin.module#AdminModule',
        canLoad: [ AuthGuardService ]
      },

После загрузки AdminModule в модуле AdminRouting мы можем использовать CanActive для защиты детей от неавторизованных пользователей, как показано ниже:

{ 
      path: '',
      component: AdminComponent,
      children: [ 
        {
          path: 'person-list',
          component: PersonListComponent,
          canActivate: [ AuthGuardService ]
        }
      ]
    }  
Мохаммад Ниазманд
источник
Значит, нужно использовать как canLoad, так и canActivate?
Тарида Джордж
0

canActivate, если неавторизованный пользователь входит, по-прежнему загружает этот модуль. вам понадобится canLoad, чтобы решить, нужно ли его загружать.

LiHao
источник
0

Важно отметить, что canLoad никому не помешает получить ваш исходный код. .Js не будет загружен браузером, если пользователь не авторизован, но вы можете принудительно выполнить загрузку вручную, выполнив импорт ('./ xxxxx.js') в консоли браузера.

Имя модуля можно легко найти на main.js в определении маршрутов.

Иван Мурицы
источник