【发布时间】:2019-07-12 05:52:26
【问题描述】:
我有两个延迟加载模块(站点和 gtd),它们都包含一些路由。我希望 gtd 组件中的所有子路由(带有“app/*”的路径)都受到 AuthGuard 的保护。我正在使用 Auth0 进行身份验证。
但无论出于何种原因,在验证后我尝试调用this.router.navigate('/app'),它总是解析为false。我已经在有和没有AuthGuard 的情况下尝试过它,它会导致相同的行为。所以我不认为这是路由守卫的问题。但以防万一,我已将其包含在此处。
没有错误消息或类似的东西。
为什么路由失败?
这是我的路线:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuardService as AuthGuard } from './core/auth/auth-guard.service';
const routes: Routes = [
{ path: '', redirectTo: 'site', pathMatch: 'full' },
{ path: 'site', loadChildren: './site/site.module#SiteModule' },
{ path: 'app', loadChildren: './gtd/gtd.module#GtdModule', canActivate: [AuthGuard]},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
这里是 AuthGuard:
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
import { Router, CanActivate } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor(public auth: AuthService, public router: Router) { }
canActivate(): boolean {
if (!this.auth.isAuthenticated()) {
console.log('Not authenticated')
this.router.navigate(['']);
return false;
}
console.log('Authentication guard satisfied.')
return true;
}
}
这是身份验证服务:
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import * as auth0 from 'auth0-js';
import { LogService } from '../util/log.service';
import { Location } from '@angular/common';
import { environment } from '../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private loginRedirect = environment.auth0.loginRedirectUrl;
private logoutRedirectTo = environment.auth0.logoutRedirectTo;
private clientID = environment.auth0.clientID;
private domain = environment.auth0.domain;
private _idToken: string;
private _accessToken: string;
private _expiresAt: number;
userProfile: any;
auth0 = new auth0.WebAuth({
clientID: this.clientID,
domain: this.domain,
responseType: 'token id_token',
redirectUri: this.loginRedirect,
scope: 'openid'
});
constructor(public router: Router, public logger: LogService, public location: Location) {
this._idToken = '';
this._accessToken = '';
this._expiresAt = 0;
}
get accessToken(): string {
return this.accessToken;
}
get idToken(): string {
return this._idToken;
}
public getProfile(cb): void {
if (!this._accessToken) {
const errMsg = 'Access Token must exist to fetch profile';
this.logger.error(errMsg);
throw new Error(errMsg);
}
const self = this;
this.auth0.client.userInfo(this._accessToken, (err, profile) => {
if (profile) {
self.userProfile = profile;
}
cb(err, profile);
});
}
login(): void {
this.auth0.authorize();
}
public handleAuthentication(): void {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
window.location.hash = '';
this.localLogin(authResult);
this.logger.log('Authentication Result:', authResult);
this.router.navigate(['/app']);
} else if (err) {
this.router.navigate(['/home']);
console.log(err);
}
});
}
private localLogin(authResult): void {
// Set isLoggedIn flag in localStorage
localStorage.setItem('isLoggedIn', 'true');
// Set the time that the access token will expire at
const expiresAt = (authResult.expiresAt * 1000) + new Date().getTime();
this._accessToken = authResult.accessToken;
this._idToken = authResult.idToken;
this._expiresAt = expiresAt;
}
public renewTokens(): void {
this.auth0.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.localLogin(authResult);
} else if (err) {
alert (`Could not get a new token (${err.error}: ${err.error_description}).`);
this.logout();
}
});
}
public logout(): void {
// Remove tokens and expiry time
this._accessToken = '';
this._idToken = '';
this._expiresAt = 0;
// Remove isLoggedIn flag from localStorage
localStorage.removeItem('isLoggedIn');
// Go back to the home route
window.location.href = `http://${this.domain}/logout?returnTo=${this.logoutRedirectTo}`;
this.router.navigate(['/']);
this.logger.info('Access token', this._accessToken);
this.logger.info('IdToken', this._idToken);
}
public isAuthenticated(): boolean {
// Check whether the current time is past the access token's expiry time
return new Date().getTime() < this._expiresAt;
}
}
我在登录回调url中加载的组件中调用handleAuthentication: 从'@angular/core'导入{组件,OnInit}; 从 'src/app/core/auth/auth.service' 导入 { AuthService };
@Component({
selector: 'app-login-callback',
templateUrl: './login-callback.component.html',
styleUrls: ['./login-callback.component.scss']
})
export class LoginCallbackComponent implements OnInit {
constructor(private authService: AuthService) { }
ngOnInit() {
console.log(this.authService.isAuthenticated())
this.authService.handleAuthentication();
}
}
我不知道为什么,但this.router.navigate() 解析为false。
【问题讨论】:
-
你试过开启路由追踪吗?这有时有助于了解可能出了什么问题:
.forRoot([])方法上的`{ enableTracing: true }`。 -
这很有帮助。我发现导航被取消,因为 navigationTrigger: "hashchange" 是由
window.location.hash = ''行触发的