Используя Angular2, как перенаправить на предыдущий URL-адрес до переадресации входа
Используя Angular2, чтобы создать одностраничное приложение, я перехватываю неавторизованный доступ пользователей к непубличным маршрутам в пользовательском RouterOutlet
и перенаправляя их на вид входа. После успешного входа в систему я хочу перенаправить пользователя в свое первоначально запрошенное представление, а не по умолчанию.
Я заметил, что Router
имеет функцию renavigate()
, которая переместится на последний успешный маршрут, но последний успешный маршрут был /auth/login
, а не запрошенный первоначально URL.
В принципе: как я могу получить доступ или определить ранее запрошенный URL?
Я действительно не хочу прибегать к передаче параметров строки запроса, если только мне это не нужно. В идеале было бы неплохо иметь доступ к коллекции history
как часть компонента Router
, аналогично backbone.history
!
Ответы
Ответ 1
- Используйте Auth Guard (реализует CanActivate), чтобы предотвратить использование пользователей, не прошедших проверку подлинности. См. официальную документацию с примерами и этот блог.
-
Используйте RouterStateSnapshot в защитнике auth для захвата запрошенного URL.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
{
// keep the attempted URL for redirecting
this._loginService.redirectUrl = state.url;
}
-
Перенаправить на этот URL-адрес на успешную аутентификацию с помощью Router (например, в login.component.ts
). Например. this._router.navigateByUrl(redirectUrl);
P.S. Предложения @MichaelOryl и @Vitali будут работать, но мой способ более согласован с окончательной версией Angular2.
Ответ 2
Вы можете найти то, что вам нужно в docs для класса Location
. Функция back()
может сделать это для вас.
Другим подходом было бы подписаться на события popstate
в Location
. MDN имеет документы, говорящие о значениях, которые вы могли бы ожидать получить.
class MyCLass {
constructor(private location: Location) {
location.subscribe((val) => {
// do something with the state that passed in
})
}
}
В противном случае вам может понадобиться служба, которая отслеживает изменения в маршрутизаторе, чтобы вы могли получить к ним доступ.
class MyTrackingService {
constructor(private router: Router) {
router.subscribe((val) => {
// store the routes here so that you can peel them off as needed?
})
}
}
В этом случае я обращаюсь к объекту Router
и подписываюсь на любые изменения, чтобы отслеживать их.
Ответ 3
Это сработало для меня. Внесите его в свой основной конструктор компонента приложения, зарегистрировав его в методе начальной загрузки.
Первым val
при загрузке страницы должен быть исходный URL.
Я отказываюсь от подписки сразу после того, чтобы быть эффективным, так как я не (возможно, еще) хочу слушать последующие события маршрутизатора в этой службе.
Внесите сервис в другие места, где требуется исходный url.
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
@Injectable()
export class UrlTrackingService {
public originalUrl: string;
constructor(
private router: Router
) {
let subscription: Subscription = this.router.events.subscribe((val) => {
this.originalUrl = val.url;
subscription.unsubscribe();
});
}
}
Ответ 4
Обновленный пример Использование Angular 2.2.1
Auth Guard, который передает исходный URL-адрес компоненту входа:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (localStorage.getItem('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login', { returnUrl: state.url }]);
return false;
}
}
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AlertService, AuthenticationService } from '../_services/index';
@Component({
moduleId: module.id,
templateUrl: 'login.component.html'
})
Входной компонент, перенаправляющий предыдущий/оригинальный URL-адрес после входа в систему:
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
returnUrl: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.params['returnUrl'] || '/';
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
// login successful so redirect to return url
this.router.navigate([this.returnUrl]);
},
error => {
// login failed so display error
this.alertService.error(error);
this.loading = false;
});
}
}
Для получения дополнительной информации и рабочей демонстрации вы можете проверить этот пост