У меня немного огурца. Я использую защиту маршрута (реализуя интерфейс CanActivate
), чтобы проверить, предоставлен ли пользователю доступ к определенному маршруту:
const routes: Routes = [
{
path: '',
component: DashboardViewComponent
},
{
path: 'login',
component: LoginViewComponent
},
{
path: 'protected/foo',
component: FooViewComponent,
data: {allowAccessTo: ['Administrator']},
canActivate: [RouteGuard]
},
{
path: '**',
component: ErrorNotFoundViewComponent
}
];
Теперь он отлично работает для защиты маршрута '/protected/foo' от активации, но я хотел бы сообщить пользователю, что маршрут, к которому он пытается получить доступ, запрещен (аналогично 403 Forbidden, который вы можете получить с сервера).
Проблема: Как я могу показать пользователю это специальное представление ошибок, не перенаправляя его на маршрут ошибок, какой из множества источников, которые я нашел, является предпочтительным? И как мне по-прежнему использовать мой RouteGuard
, фактически не загружая запрещенный маршрут, потому что, если я проверяю доступ внутри моего FooViewComponent
и отображаю другое представление, это как бы побеждает точку наличия RouteGuard
в первую очередь.
В идеале я хотел бы, чтобы мой RouteGuard
не только возвращал false в методе canActivate()
, но и полностью заменял компонент, скажем, ErrorForbiddenViewComponent
. Но я понятия не имею, как это сделать, или это возможно. Любые альтернативы?
Вот так теперь выглядит мой route guard:
import {Injectable} from '@angular/core';
import {Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {AuthService} from '../services/auth.service';
@Injectable()
export class RouteGuard implements CanActivate {
constructor(
private router: Router,
private auth: AuthService
) {}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const { auth, router } = this;
const { allowAccessTo } = next.data;
const identity = auth.getIdentity();
if (
identity &&
allowAccessTo.indexOf(identity.role)
) {
// all good, proceed with activating route
return true;
}
if (identity) {
// TODO show ErrorForbiddenViewComponent instead of redirecting
console.log('403 Forbidden >>', next);
}
else {
// not logged in: redirect to login page with the return url
const [returnUrl, returnQueryParams] = state.url.split('?');
console.log('401 Unauthorised >>', returnUrl, returnQueryParams, next);
router.navigate(['/login'], {queryParams: {returnUrl, returnQueryParams}});
}
return false;
}
}
Поэтому я просто предотвращаю загрузку маршрута, но не перенаправляю. Я перенаправляю только незарегистрированных посетителей на маршрут входа.
Рассуждение:
- Маршруты должны отражать определенное состояние приложения — посещение URL-адреса маршрута должно воссоздавать это состояние.
- Наличие маршрутов ошибок (кроме 404 Not Found) означает, что ваше приложение может фактически воссоздавать состояния ошибок. Это не имеет смысла, так как зачем вам сохранять состояние ошибки как состояние вашего приложения? В целях отладки следует использовать журналы (консольные или серверные), повторный просмотр страницы с ошибкой (т.е. обновление страницы) может помешать этому.
- Кроме того, перенаправляя приложение на маршрут ошибок, оно должно предоставить пользователю некоторое представление об ошибке. В этом отношении либо какой-либо параметр необходимо будет передать через URL-адрес, либо (что гораздо хуже) сохранить состояние ошибки в какой-либо службе ошибок и получить его при доступе к маршруту ошибки.
- Кроме того, игнорирование RouteGuard и простая загрузка компонента и проверка доступа внутри него могут привести к загрузке некоторых дополнительных зависимостей, которые в любом случае не будут использоваться (поскольку пользователю это не разрешено), что делает всю ленивую загрузку намного сложнее.
У кого-нибудь есть какое-то решение для этого? Мне также интересно, как получилось, что после столь долгого существования Angular 2+ ни у кого раньше не было такой ситуации? У всех нормально с перенаправлением?
Также имейте в виду, что хотя в настоящее время я использую FooViewComponent
синхронно, это может измениться в будущем!
ComponentFactory
, как описано в blog.mgechev.com/2015/09/30/ и заменить сам компонент наAccessForbidden
- person Tarun Lalwani   schedule 29.05.2018