问题描述
我的 Angular 应用程序需要在进行服务调用之前检查令牌是否过期。在访问此应用程序之前,NodeJS/Express+Middleware 路由应用程序管理对 OIDC 服务的身份验证。请注意,这适用于已经拥有 OIDC 令牌发行服务器的大型公司(抱歉不确定这叫什么)。
如果令牌过期,则需要将整个应用重新路由到登录页面。我之前问过并了解到我需要在我的 Angular 应用程序中添加一个 AuthGuard 以促进这一点。我想我有一个很好的例子并且可以做到这一点,除了检测过期令牌的部分。不知何故,我需要检查会话是否通过身份验证。
我想要一个可以帮我检查这 3 个状态的包:
- 没有Token,用户需要登录。这部分应该是上面提到的中间件认证服务器处理的。尽管如此,如果用户以某种方式访问应用程序,AuthGuard 路由将收到通知,应用程序会将用户重定向到登录页面。
- 令牌在那里,但已过期。如果是这种情况,系统会通知 AuthGuard 路由,并且应用会将用户重定向到登录页面。
- 令牌在那里,有效。如果是这种情况,AuthGuard 会让用户按照他们的意愿行事。
在中间件包中,我使用了 Passport。对于 Angular,我不想弄清楚我需要检查什么标头或 cookie,弄清楚如何解析值、检查过期时间或其他方式。我会研究 okta,但我不确定他们是否希望您使用他们的身份验证服务器。我希望有最简单的方法。
解决方法
让我们考虑这样一种情况,您在一个模块下有登录组件,而在另一个模块下有其余的路由,这将被称为 ExampleModule。
您可以像这样将守卫传递给示例模块:
export const layoutRoutes: Routes = [
{
path: '',redirectTo: 'login',pathMatch: 'full'
},{
path: 'examplePage',loadChildren: () => import('./example/example.module').then(m => m.ExampleModule),canActivate: [AuthenticationGuard]
}
]
在 AuthenticationGuard 中,您可以调用一个服务来说明您的使用是否可以继续:
@Injectable({ providedIn: 'root' })
export class AuthenticationGuard implements CanActivate {
constructor(private _auth: AuthenticationService,private _router: Router) { }
/**
* Implementation of the CanActivate interface that evaluates whether the
* user is allowed to access the given route.
* @param route ActivatedRouteSnapshot
* @param state RouterStateSnapshot
* @returns a boolean that the router uses to allow/refuse navigation
*/
canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean {
const isAuthenticated = this._auth.canNavigate();
if (!isAuthenticated) this._router.navigate(['/login']);
return isAuthenticated;
}
几点:
- AuthenticationService 是带有指示用户是否通过身份验证的代码的服务,此代码不会在整个应用程序中传播。
- 只有当结果为真时,守卫才会导航到路由,否则,它会再次导航到登录页面。