Piszę małą aplikację AngularJS, która ma widok logowania i widok główny, skonfigurowane w następujący sposób:
$routeProvider
.when('/main' , {templateUrl: 'partials/main.html', controller: MainController})
.when('/login', {templateUrl: 'partials/login.html', controller: LoginController})
.otherwise({redirectTo: '/login'});
Mój LoginController sprawdza kombinację użytkownik / hasło i ustawia właściwość w $ rootScope odzwierciedlającą to:
function LoginController($scope, $location, $rootScope) {
$scope.attemptLogin = function() {
if ( $scope.username == $scope.password ) { // test
$rootScope.loggedUser = $scope.username;
$location.path( "/main" );
} else {
$scope.loginError = "Invalid user/pass.";
}
}
Wszystko działa, ale jeśli uzyskam dostęp http://localhost/#/main
, w końcu pomijam ekran logowania. Chciałem napisać coś w stylu „za każdym razem, gdy zmienia się trasa, jeśli $ rootScope.loggedUser ma wartość NULL, to przekieruj do / login”
...
... czekaj. Czy mogę w jakiś sposób słuchać zmian trasy? I tak opublikuję to pytanie i będę szukał dalej.
Odpowiedzi:
Po przejrzeniu dokumentacji i kodu źródłowego, myślę, że to działa. Być może będzie to przydatne dla kogoś innego?
Do mojej konfiguracji modułu dodałem następujące elementy:
Jedną rzeczą, która wydaje się dziwna, jest to, że musiałem przetestować częściową nazwę (
login.html
), ponieważ obiekt „next” Route nie miał adresu URL ani czegoś innego. Może jest lepszy sposób?źródło
Oto być może bardziej eleganckie i elastyczne rozwiązanie z właściwością konfiguracyjną „rozstrzygnij” i „obiecuje”, że w końcu wczytuje dane dotyczące routingu i reguł routingu w zależności od danych.
Funkcję określa się w „rozwiązaniu” w konfiguracji routingu oraz w funkcji ładowania i sprawdzania danych, wykonaj wszystkie przekierowania. Jeśli musisz załadować dane, zwrócisz obietnicę, a jeśli musisz dokonać przekierowania - przedtem odrzuć obietnicę. Wszystkie szczegóły można znaleźć na stronach z dokumentacją $ routerProvider i $ q .
Dla osób mówiących po rosyjsku jest post na habr „ Вариант условного раутинга в AngularJS ”.
źródło
ui.router
jest używany, użyj$stateProvider
zamiast$routeProvider
.Próbowałem zrobić to samo. Wymyśliłem inne prostsze rozwiązanie po pracy z kolegą. Mam ustawiony zegarek
$location.path()
. To załatwia sprawę. Właśnie zaczynam się uczyć AngularJS i uważam, że jest to bardziej przejrzyste i czytelne.źródło
Innym sposobem implementacji przekierowania logowania jest użycie zdarzeń i przechwytywaczy, jak opisano tutaj . W artykule opisano niektóre dodatkowe zalety, takie jak wykrywanie, kiedy wymagane jest logowanie, kolejkowanie żądań i odtwarzanie ich po pomyślnym zalogowaniu.
Możesz wypróbować działające demo tutaj i wyświetlić źródło demo tutaj .
źródło
1. Ustaw globalnego bieżącego użytkownika.
W usłudze uwierzytelniania ustaw aktualnie uwierzytelnionego użytkownika na zakres główny.
2. Ustaw funkcję autoryzacji dla każdej chronionej trasy.
3. Sprawdź autoryzację przy każdej zmianie trasy.
Alternatywnie można ustawić uprawnienia do obiektu użytkownika i przypisać każdej trasie uprawnienia, a następnie sprawdzić uprawnienia w wywołaniu zwrotnym zdarzenia.
źródło
if (!user && !next.$$route.public)
next.$$route
mi wyjaśnić ? Nie znalazłem nic w dokumentach Angular, które opisywałyby argumenty związane z$routeChangeStart
wydarzeniem, ale zakładamnext
i czycurr
są jakieś obiekty lokalizacji?$$route
Nieco trudno google.$$route
właściwość jest prywatną zmienną Angulara. Nie powinieneś na tym polegać, patrz na przykład: stackoverflow.com/a/19338518/1132101 - jeśli tak, kod może się zepsuć, gdy zmieni się Angular.$route.routes
zbudować listę (jak na @ thataustin odpowiedź): uzyskać ścieżkę do lokalizacji znext.originalPath
i używa ich do indeksu$route.routes
:var auth = $route.routes[next.originalPath]
.Oto jak to zrobiłem, na wypadek gdyby komukolwiek to pomogło:
W konfiguracji ustawiam
publicAccess
atrybut na kilku trasach, które chcę otworzyć dla publiczności (np. Logowanie lub rejestracja):następnie w bloku uruchomieniowym ustawiam detektor
$routeChangeStart
zdarzenia, które przekierowuje,'/login'
chyba że użytkownik ma dostęp lub trasa jest publicznie dostępna:Możesz oczywiście zmienić warunek z
isLoggedIn
dowolnego innego ... po prostu pokazując inny sposób na zrobienie tego.źródło
nextLoc.$$route.publicAccess
Btw.$route.routes[nextLoc.originalPath]
, który nie używa zmiennej prywatnej.nextLoc && nextLoc.publicAccess
!Robię to za pomocą przechwytywaczy. Utworzyłem plik biblioteki, który można dodać do pliku index.html. W ten sposób będziesz mieć globalną obsługę błędów dla połączeń z usługami odpoczynku i nie będziesz musiał dbać o wszystkie błędy indywidualnie. W dalszej części wkleiłem również moją bibliotekę logowania podstawowego uwierzytelniania. Tam widać, że sprawdzam również błąd 401 i przekierowuję do innej lokalizacji. Zobacz lib / ea-basic-auth-login.js
lib / http-error-handling.js
css / http-error-handling.css
index.html
lib / ea-basic-auth-login.js
Prawie to samo można zrobić przy logowaniu. Tutaj masz odpowiedź na przekierowanie ($ location.path („/ login”)).
źródło
W pliku app.js:
źródło
Możliwe jest przekierowanie do innego widoku za pomocą routera kątowego . W tym celu mamy metodę
$state.go("target_view")
. Na przykład:źródło
Jeśli nie chcesz używać routera kątowego-ui, ale chciałbyś, aby twoje kontrolery były leniwie ładowane przez RequireJS, istnieje kilka problemów ze zdarzeniami,
$routeChangeStart
gdy używasz swoich kontrolerów jako modułów RequireJS (leniwie załadowanych).Nie możesz być pewien, że kontroler zostanie załadowany przed
$routeChangeStart
uruchomieniem - w rzeczywistości nie zostanie załadowany. Oznacza to, że nie możesz uzyskać dostępu do właściwościnext
trasy, takich jaklocals
lub,$$route
ponieważ nie zostały one jeszcze skonfigurowane.Przykład:
Oznacza to, że nie można tam sprawdzić praw dostępu.
Rozwiązanie:
Ponieważ ładowanie kontrolera odbywa się za pomocą rozwiązania, możesz zrobić to samo z kontrolą kontroli dostępu:
Zauważ, że zamiast używać zdarzenia,
$routeChangeStart
którego używam$routeChangeError
źródło
źródło