Różnica między canLoad i canActivate w Angular?

105

Jaka jest różnica między canLoadi 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;
}

Kiedy powinienem, który z nich?

Yoav Schniederman
źródło

Odpowiedzi:

105

canActivate służy do uniemożliwienia nieautoryzowanym użytkownikom dostępu do niektórych tras. Zobacz dokumentację, aby uzyskać więcej informacji.

canLoad służy do zapobiegania leniwemu ładowaniu całych modułów przez aplikację, jeśli użytkownik nie jest do tego upoważniony.

Zobacz dokumentację i przykład poniżej, aby uzyskać więcej informacji.

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

Za pomocą tego kodu kod modułu AdminModule zostanie załadowany do aplikacji tylko wtedy, gdy zwróci AuthGuard true.

Jeśli użytkownik nie jest upoważniony do dostępu do tej trasy, a użyliśmy tylko canActivatestrażnika, AdminModulezostanie załadowany, nawet jeśli użytkownik nie miałby dostępu do tej trasy.

Fredrik Lundin
źródło
7
Jeśli użyję canActivatew powyższym scenariuszu, jaka będzie różnica?
k11k2
3
@ k11k2 z canActivemodułem zostanie załadowany (F12> Źródła - w chrome). Możesz tam zobaczyć pliki .js, z canLoadtymi modułami (pliki .js) nie zostaną załadowane :) Sprawdź moją odpowiedź powyżej, gdzie wyjaśniłem to lepiej
DiPix
23
A co ze scenariuszem, w którym administrator zalogował się, więc moduł administratora został załadowany za pośrednictwem, canLoadzwraca true, a następnie wylogowuje się z aplikacji. Teraz użytkownik niebędący administratorem loguje się w tej samej przeglądarce, jak to działa? Czy załadowany moduł został eksmitowany lub usunięty z pamięci podręcznej?
Keerthivasan
2
@Keerthivasan nic nie wymusza usunięcia wcześniej załadowanego fragmentu leniwego modułu AdminModule, gdy użytkownik wylogował się i zalogował się ponownie na inne konto, które nie ma wystarczających uprawnień, aby załadować moduł AdminModule. Jednak i tak nie uzyskasz dostępu ... poza załadowanym modułem buforowanym. Nie sądzę, że jest to prawdziwy problem z bezpieczeństwem, ponieważ zwykle jedno urządzenie to jeden prawdziwy użytkownik
hastrb
1
@ sgClaudia98 możesz używać obu, ale obowiązuje ścisła kolejność wykonywania strażników. dlatego w twoim przypadku nie ma różnicy, jeśli chodzi o to, co powiedziałem trochę wcześniej. Myślę, że w moim pierwszym komentarzu umieściłem bardzo szczegółowe wyjaśnienie. Byłby to dość dziwny przypadek, gdyby obecnie jedno urządzenie i administrator / nie administrator logują się jedno po drugim.
hastrb
36
  • CanActivate - decyduje, czy trasa może zostać aktywowana, ta ochrona może nie być najlepszym sposobem dla modułów funkcji, które są ładowane z opóźnieniem, ponieważ strażnik zawsze ładuje moduł do pamięci, nawet jeśli strażnik zwrócił błąd, co oznacza, że ​​użytkownik nie ma uprawnień dostępu trasa.
  • CanLoad - decyduje, czy moduł może być ładowany leniwie, kontroluje, czy można w ogóle załadować trasę. Jest to przydatne w przypadku modułów funkcji, które są ładowane z opóźnieniem. Nie załadują się nawet, jeśli strażnik zwróci fałsz.

To jest test, który przeprowadziłem na obu strażnikach z modułem funkcji, który jest ładowany leniwie:

1. CanActivate Guard Test

zauważysz na dole strony Network, że wysłał 24 żądania o rozmiarze 9,5 MB, które zostały przesłane w 3,34 sekundy i w pełni załadowane w 3,47 sekundy.

CanActivate Guard Test On Lazy Loaded Feature Module

1. Test CanLoad Guard

tutaj zobaczysz dużą różnicę, gdy użyliśmy CanLoad Guard, ponieważ przeglądarka przesłała tylko 18 żądań o rozmiarze 9,2 MB, które zostały przesłane, kończąc w 2,64 sekundy i w pełni ładując 2,59 sekundy.

Test CanLoad Guard na leniwie ładowanym module funkcji

CanLoad Guard nigdy nie ładuje danych modułu, jeśli użytkownik nie jest autoryzowany, co zapewnia większą wydajność, ponieważ czas ładowania zmniejszył się o prawie 1 sekundę, a to jest ogromny czas wczytywania stron internetowych, bez wątpienia zależy to od rozmiaru modułu.

Wskazówka: jeśli chcesz wykonać test na swoim projekcie upewnij się, że Disable Cachecheckbox w zakładce sieci jest zaznaczony, jest zaznaczony na pierwszym obrazku

Mahmoud Fawzy
źródło
4
Tylko po to, żeby nikogo nie pomylić .. 403 to Forbbiden, a nie Unauthorized, czyli 401.
hastrb
ten strażnik zawsze załaduje moduł do pamięci, nawet jeśli strażnik zwrócił fałszywy, myślę, że to zachowanie nie jest odpowiednie. Lepiej byłoby nie ładować modułu, gdy canActivatezwraca false
Olivier Boissé
20

Odnośnie pytania z komentarzy w innym poście „Jeśli użyję canActivate w powyższym scenariuszu, jaka będzie różnica?”

Właściwie dla użytkownika nie będzie różnicy, nie uzyska on dostępu do strony w obu przypadkach. Chociaż jest jedna ukryta różnica . Jeśli naciśniesz F12 i przejdziesz do Źródła (w Chrome), gdzie są pobierane pliki. Następnie możesz zobaczyć, że w przypadku canActive został pobrany plik z kodem ( chunk.js ). Nawet jeśli nie masz dostępu do strony. wprowadź opis obrazu tutaj

Ale w przypadku canLoad nie będzie pliku chunk.js z kodem źródłowym.

wprowadź opis obrazu tutaj

Jak więc widzisz, ma to naprawdę duży wpływ na bezpieczeństwo.

I oczywiście nie zapominaj, że canLoad może być używany tylko dla modułów LazyLoaded .

DiPix
źródło
3
nie widzę żadnych fragmentów do leniwego ładowania modułu na mojej karcie sieciowej, ale trasy działają zgodnie z oczekiwaniami.
k11k2
@ k11k2, jeśli chcesz zobaczyć, którego pliku jest częścią moduł, po prostu dodaj debugger;instrukcję w konstruktorze dla jednego ze składników tego modułu. Możesz wtedy sprawdzić, czy został załadowany jako oddzielny fragment lub zawarty w module, takim jak main. Jeśli masz odwołania do komponentów w leniwym module, które nie są odizolowane od tego modułu, może on i tak zostać załadowany. Jeśli to widzisz, sugeruje to, że filtrujesz według czegoś innego niż pliki JS lub musisz podzielić swój leniwy moduł na zwykłe i „naprawdę leniwe” części.
Simon_Weaver
@ k11k2 Myślę, że twój "moduł z leniwym ładowaniem" nie jest ładowany leniwie. Upewnij się, że użyłeś loadChildrenproperty jako części ścieżki do twojego leniwego modułu.
hastrb
18

CanLoad Straż uniemożliwia ładowanie Lazy Loaded Module. Zwykle używamy tego strażnika, gdy nie chcemy, aby nieautoryzowany użytkownik nawigował do żadnej z tras modułu, a także zatrzymał się, a nawet zobaczył kod źródłowy modułu.

Angular zapewnia canActivate Guard, który uniemożliwia nieautoryzowanemu dostęp do trasy. Nie przeszkadza to jednak w pobieraniu modułu. Użytkownik może użyć konsoli programisty chrome, aby zobaczyć kod źródłowy. CanLoad Guard zapobiega pobieraniu modułu.

W rzeczywistości CanLoad chroni moduł do załadowania, ale po załadowaniu modułu ochrona CanLoad nic nie zrobi. Załóżmy, że zabezpieczyliśmy ładowanie modułu za pomocą ochrony CanLoad dla nieuwierzytelnionego użytkownika. Gdy użytkownik jest zalogowany, moduł będzie można załadować i będziemy mogli nawigować po ścieżkach podrzędnych skonfigurowanych przez ten moduł. Ale gdy użytkownik jest wylogowany, nadal będzie mógł nawigować po ścieżkach podrzędnych, ponieważ moduł jest już załadowany. W takim przypadku, jeśli chcemy zabezpieczyć ścieżki podrzędne przed nieautoryzowanymi użytkownikami, musimy również użyć osłony CanActivate .

Użyj CanLoad przed załadowaniem modułu AdminModule:

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

Po załadowaniu AdminModule, w module AdminRouting możemy użyć CanActive do ochrony dzieci przed nieautoryzowanymi użytkownikami, jak poniżej:

{ 
      path: '',
      component: AdminComponent,
      children: [ 
        {
          path: 'person-list',
          component: PersonListComponent,
          canActivate: [ AuthGuardService ]
        }
      ]
    }  
Mohammad niazmand
źródło
Więc należy używać zarówno canLoad, jak i canActivate?
Tarida George
bardzo ładnie wyjaśnione:
kciuk w górę
Uwaga: CanActivate uruchamia się przy każdej zmianie trasy, ale canLoad jest uruchamiany tylko przy pierwszym załadowaniu modułu. Jeśli masz logikę, która musi działać za każdym razem, gdy odwiedzana jest trasa, musisz użyć canActivate (lub przenieść logikę w inne miejsce). Zarówno canActivate, jak i canLoad mogą być używane razem.
Stevethemacguy
Możesz również umieścić canActivate obok canLoad na najwyższym poziomie, aby zablokować wszystkie trasy podrzędne bez konieczności dodawania canActivate do każdej trasy podrzędnej.
Stevethemacguy
16

canActivate służy do zapobiegania nieautoryzowanemu użytkownikowi

canLoad służy do zapobiegania całemu modułowi aplikacji

Przykład canActivate :

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

Przykład canLoad :

{ path: 'user' , canLoad: [AuthenticGuard], loadChildren : './user/user.module#UserModule' }
Sagar Jadhav
źródło
Dla przyszłych czytelników przykład canActive nie jest leniwy, ale canLoad jest… z powodu posiadania loadChildren. Co więcej, najnowsza wersja loadChildren: () => import('./user/user.module').then(m => m.UserModule)
angular
Bardzo proste wyjaśnienie, podobało mi się :)
KTM
0

canActivate, jeśli wejdzie nieautoryzowany użytkownik, nadal ładuje ten moduł. Potrzebujesz canLoad, aby ocenić, czy należy go załadować.

LiHao
źródło
0

Warto zauważyć, że canLoad nie powstrzyma nikogo przed uzyskaniem Twojego kodu źródłowego. Plik .js nie zostanie pobrany przez przeglądarkę, chyba że użytkownik ma autoryzację, ale możesz wymusić ręczne pobranie, wykonując import („./ xxxxx.js”) w konsoli przeglądarki.

Nazwę modułu można łatwo znaleźć w pliku main.js w definicji tras.

Ivan Muricy
źródło