【问题标题】:Run a service before application or components load Angular 7在应用程序或组件加载 Angular 7 之前运行服务
【发布时间】:2020-05-07 15:17:26
【问题描述】:

我正在使用 Angular 7 构建一个应用程序,我已经处理了 API 调用,使用 C# 的 JWT 令牌认证系统,并在必要时更新了 LocalStorage(),当用户登录和注销时,所有这些都是工作完美。

我的问题是我希望它作为应用程序中的中间件而不是在生命周期方法上运行登录检查 - ng.onInit()。我该怎么办?

有没有办法将生命周期事件作为入口组件或服务来执行。也就是说,在加载任何组件之前,它能够检查用户是否登录并通过路由器重定向到所需的页面。

【问题讨论】:

  • 如果你做一个单例,应用程序中只会存在一个服务实例。也许这会有所帮助? angular.io/guide/singleton-services
  • 使用APP_INITIALIZERstackoverflow.com/questions/49707830/…
  • 你可以试试Can Activate接口,让它和中间件一样angular.io/api/router/CanActivate
  • 您可以在 app.component.ts 中处理登录检查,您只需在其中注入服务即可。然后在本地存储中设置该值。然后,您可以使用自定义 Guard 来限制对页面的访问。此外,如果他们已登录,请将服务中的 bool 设置为 true。然后将该身份验证服务注入其他组件并检查该值。不过只在 app.component.ts 中设置值。

标签: javascript angular typescript angular7


【解决方案1】:

你应该实现一个authGuardService 或类似的东西作为你的路由中间件(使用 canActivate 部分)

见:https://angular.io/api/router/CanActivate

这可以防止在 canActivate 条件失败时加载路由(在使用登录系统等而不是检查生命周期挂钩时,这是首选)。

【讨论】:

    【解决方案2】:

    您应该检查 Guard 的角度,尤其是 canActivate Guard:https://angular.io/guide/router

    一个守卫是这样创建的:

    @Injectable({
      providedIn: 'root'
    })
    export class MyGuard implements CanLoad {
     constructor() {}
    
     canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | 
     Promise<boolean> | boolean {
       const x = true;
       if (x) {
         return true; // It allows access to the route;
       } else {
          // redirect where you want;
         return false; // it doesnt allow to access to the route
      }
     }
    }
    

    然后在你的路由模块中:

    {
    path: "yourRoute",
    canActivate: [MyGuard],
    component: YourComponent
    }
    

    对于身份验证,您有一个很好的库,在这里使用了警卫: https://www.npmjs.com/package/ngx-auth

    【讨论】:

    • 你好,请你再次检查你的代码,在它说Observable&lt;boolean&gt; | Promise&lt;boolean&gt;boolean的那一行我在这里遇到一个错误,'boolean' 仅指一种类型,但被用作一个值在这里,请帮忙看看。
    • 是的,对不起,是打字错误,函数canActivate可以返回布尔值,或者promise或者observable(我编辑过)
    • 如何在 app.module.ts 上以entrycomponentthe providers arraythe declarations array 的形式加载myGuard,还是应该省略它。?
    • 通常作为提供者,但是如果你使用了@Injectable([ providedIn: 'root'}) 注解,小心,你不需要将它添加到提供者:[]。它将在根范围内自动提供。
    • 好的,谢谢,它通过在用户注销时按预期限制页面来工作,但是当您最终登录时,它会抛出一个Invalid CanActivate guard Error: Invalid CanActivate guard
    【解决方案3】:

    Guard 基于路由...所以我认为您应该更喜欢模块/服务解决方案。

    import { APP_INITIALIZER } from '@angular/core';

    然后像这样将其添加为提供者:

     export function initApp(initService: YourInitService) {
      return () => { 
        initService.Init();
      }
    }
        { provide: APP_INITIALIZER,useFactory: initApp, deps: [YourInitService], multi: true } 
    

    【讨论】:

    • 提示:你也可以为 APP_INITIALIZER 返回一个 Promise。 (return initService.init()) 等待加载完成。 (为 UX 显示加载指示器。这比黑屏要好。)
    【解决方案4】:

    基于令牌过期的路由决策

    如果您使用 JSON Web 令牌 (JWT) 来保护您的 Angular 应用程序(我建议您这样做),决定是否应该访问路由的一种方法是检查令牌的过期时间.您可能正在使用 JWT 让您的用户访问您后端上受保护的资源。如果是这种情况,如果令牌过期,令牌将无用,因此这很好地表明用户应被视为“未经过身份验证”。

    在您的身份验证服务中创建一个方法来检查用户是否已通过身份验证。同样,为了使用 JWT 进行无状态身份验证,这只是令牌是否过期的问题。 angular2-jwt 中的 JwtHelperService 类可用于此目的。

    // src/app/auth/auth.service.ts
    import { Injectable } from '@angular/core';
    import { JwtHelperService } from '@auth0/angular-jwt';
    @Injectable()
    export class AuthService {
      constructor(public jwtHelper: JwtHelperService) {}
      // ...
      public isAuthenticated(): boolean {
        const token = localStorage.getItem('token');
        // Check whether the token is expired and return
        // true or false
        return !this.jwtHelper.isTokenExpired(token);
      }
    }
    

    注意:此示例假设您将用户的 JWT 存储在本地存储中。

    创建一个实现路由保护的新服务。你可以随意调用它,但是像 auth-guard.service 这样的东西通常就足够了。

    // src/app/auth/auth-guard.service.ts
    import { Injectable } from '@angular/core';
    import { Router, CanActivate } from '@angular/router';
    import { AuthService } from './auth.service';
    @Injectable()
    export class AuthGuardService implements CanActivate {
      constructor(public auth: AuthService, public router: Router) {}
      canActivate(): boolean {
        if (!this.auth.isAuthenticated()) {
          this.router.navigate(['login']);
          return false;
        }
        return true;
      }
    }
    

    该服务注入 AuthServiceRouter 并有一个名为 canActivate 的方法。此方法是正确实现 CanActivate 接口所必需的。

    canActivate 方法返回一个布尔值,指示是否应允许导航到路线。如果用户未通过身份验证,他们将被重新路由到其他地方,在这种情况下,路由称为 /login。 现在可以将守卫应用于您希望保护的任何路线。

    // src/app/app.routes.ts
    import { Routes, CanActivate } from '@angular/router';
    import { ProfileComponent } from './profile/profile.component';
    import { 
      AuthGuardService as AuthGuard 
    } from './auth/auth-guard.service';
    export const ROUTES: Routes = [
      { path: '', component: HomeComponent },
      { 
        path: 'profile',
        component: ProfileComponent,
        canActivate: [AuthGuard] 
      },
      { path: '**', redirectTo: '' }
    ];
    

    /profile 路由现在有一个额外的配置值:canActivate。上面创建的 AuthGuard 被传递给 canActivate 的数组,这意味着它会在有人尝试访问 /profile 路由时运行。如果用户通过了身份验证,他们就会到达路由。如果没有,它们将被重定向到 /login 路由。

    注意:canActivate 守卫仍然允许激活给定路由的组件(但不导航到)。如果我们想完全阻止激活,我们可以使用 canLoad 守卫。

    更多信息here

    【讨论】:

      猜你喜欢
      • 2019-02-27
      • 2022-11-30
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多