Angular 7 CanActivate Guards при сбое

У меня есть охранники CanActivate на всех моих маршрутах, и они не работают.

Например, у меня есть два охранника:

export class AuthenticationGuard implements CanActivate {
    constructor(private as: AuthenticationService, private router: Router) { }

    canActivate() {
        if (this.as.isLoggedIn()) {
            return true;
        }

        this.router.navigate(['/login']);

        return false;
     }
    }

export class IsAdminGuard implements CanActivate {
    constructor(private us: UserService, private router: Router) { }

    canActivate() {
        if (this.us.isAdmin()) {
            return true;
        }

        this.router.navigate(['/home']);

        return false;
    }
}

И мой маршрут охраняет

const routes: Routes = [
    {
        path: 'home',
        component: DashboardComponent,
        canActivate: [AuthenticationGuard, IsAdminGuard]
    }
];

@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
});

Происходит следующее: если AuthenticationGuard терпит неудачу, он иногда проверяет IsAdminGuard и вместо того, чтобы перенаправлять кого-то на /login, когда они не аутентифицированы, они отправляются на /home, что отправляет их на другую страницу с ошибкой, потому что они не аутентифицированы. аутентифицированы и не являются администраторами, и охранники должны были выгнать их при первом сбое.

Я могу воспроизвести проблему в 100% случаев, если удалю аутентификационный jwt, который AuthenticationService проверяет при вызове isLoggedIn(), обновлю маршрут /home и смогу отследить AuthenticationGuard, возвращающий false, и все еще вызывающий IsAdminGuard

Вот код для isLoggedIn()

isLoggedIn = () => {
    const token = this.get();
    const decoded = this.decode(token);

    return token && this.isNotExpired(decoded);
};  

decode = (token: string) => {
    const validToken = () => parts.length < 3
    const parts = token ? token.split('.') : '';

    if (!token || validToken()) {
        return '{}';
    }

    const payload = validToken() ? parts[1] : '{}';

    return JSON.parse(atob(payload));
};

private isNotExpired = (decodedToken) => this.getExpiryFrom(decodedToken) > new Date();

private getExpiryFrom = (decodedToken) => new Date(decodedToken.exp * 1000);

мысли?


person nbpeth    schedule 27.11.2018    source источник
comment
Что произойдет, если вы измените порядок охранников в массиве CanActivate?   -  person Ben Steward    schedule 27.11.2018
comment
Является ли isLoggedIn() асинхронным?   -  person Phix    schedule 27.11.2018
comment
@Phix это синхронно - он просто проверяет срок действия токена авторизации   -  person nbpeth    schedule 27.11.2018
comment
Вы можете опубликовать это здесь, чтобы охватить все базы   -  person Phix    schedule 27.11.2018
comment
@BenSteward, это весело, если я их переверну, все работает нормально. хотя это не логический порядок, в котором они должны работать   -  person nbpeth    schedule 27.11.2018
comment
Вероятно, он проверяет оба, поэтому, даже если первый терпит неудачу, он все еще поражает второй, а затем направляется домой.   -  person Ben Steward    schedule 27.11.2018
comment
@Phix добавил код для вас   -  person nbpeth    schedule 27.11.2018
comment
@BenSteward правильно - добавление журналов к двум блокам сбоев каждого охранника показывает, что они все еще вызываются и возвращают false   -  person nbpeth    schedule 27.11.2018
comment
FWIW, в своих authguards я маршрутизацию не делаю. Я просто вызываю функцию выхода из службы авторизации, поэтому маршрутизация обрабатывается единообразно, а любые аномалии устраняются.   -  person Ben Steward    schedule 27.11.2018
comment
Это отличное предложение, от которого я могу отказаться. Я все еще раздражен, так как понимаю, что они не должны каскадироваться, но я новичок в угловых   -  person nbpeth    schedule 27.11.2018
comment
@BenSteward, который сделал свое дело. Я вытащил логику маршрутизации в службу авторизации. если вы хотите добавить новый ответ или немного изменить свой, я могу его отметить - спасибо за помощь, ребята.   -  person nbpeth    schedule 27.11.2018


Ответы (1)


Рассмотрите возможность работы в коротком замыкании с вашим isAdmin Guard, который перепроверяет статус аутентификации. Таким образом, правдивость аутентификации никогда не будет переопределена тем, как окажется правдивость вашего isAdmin. Это может показаться излишним, но это сработает.

person Ben Steward    schedule 27.11.2018
comment
да, я пробовал это, и это определенно работает - хотя я действительно хотел, чтобы каждый охранник был атомарным - надеялся избежать их объединения и, возможно, выявить основную проблему. - person nbpeth; 27.11.2018