代码之家  ›  专栏  ›  技术社区  ›  Anand

角度身份验证

  •  0
  • Anand  · 技术社区  · 7 年前

    我正在尝试使用sessionStorage存储在AppComponent的ngInit中检索到的用户信息。 但由于此检索使用httpClient,因此它就像是在存储键值之前就可以在另一个组件中访问。这是唯一一次设置此键。

    @Injectable()
    export class AuthService {
    
      public currentuser = new BehaviorSubject<User>(<User>JSON.parse(sessionStorage.getItem('currentuser')));
    
      constructor(private _http: HttpClient, private _trace: TraceService) { }
    
      public  authenticate(): void {
         this._http.get<User>(AppSettings.AuthUrl, {withCredentials: true})
                          .subscribe(user => {
                            sessionStorage.setItem('currentuser', JSON.stringify(user));
                            this.currentuser.next(user);
                          },
                               e => {
                                 if (e.status === 403) {
                                  this.currentuser.next(null);
                                  this._trace.handleAuthError(e);
                                 } else {
                                   this.currentuser.next(null);
                                   this._trace.handleError('Authenticating...', e);
                                 }
                               });
    
      }
    }
    

    在auth guard组件中,我有

    @Injectable()
    export class AuthGuard implements CanActivate {
    
      constructor(private _router: Router,
                  private _authService: AuthService) { }
    
      public canActivate() {
        this._authService.currentuser.subscribe(u => {
          if (u === null) {
            this._router.navigateByUrl(AppSettings.NotAuthenticatedRoute);
            return false;
          }});
        return true;
      }
    }
    

    路由模块

    const routes: Routes = [ { path: AppSettings.LegalTermsRoute,  component: LegalTermComponent, canActivate: [AuthGuard] }];
    

    在AppComponent中

      ngOnInit(): void {
          this._authService.authenticate();
      }
    

    问题是我没有正确设置此订阅,当应用程序启动时,auth guard会阻止LegalTermComponent

    2 回复  |  直到 7 年前
        1
  •  1
  •   Explosion Pills    7 年前

    sessionStorage.getItem 返回一个值,因此我不确定您是否能够使用 Observable.from 但我想这对你有用。这更像 Observable.of --无论哪种方式,这都会将一个值转换为一个可观察值,该值立即发出,然后完成,这不是您想要的。

    您需要创建一个自定义的可观察对象,该对象在可用时发出值。 BehaviorSubject 这一点很有用,因为任何时候你订阅它,你都会得到它的最后一个值,这将允许你获得所说的值,即使你碰巧在值设置后订阅了它。

    export class AuthService {
      currentuser = new BehaviorSubject<User>(sessionStorage.getItem('currentuser') as User);
    
      authenticate() {
        // Do whatever authenticate usually does ... this is an example
        this.http.post<User>('/auth').subscribe(user => this.currentuser.next(user));
      }
      /* your other methods and properties ... */
    

    我还将避免在组件中实现副作用(例如更新会话存储),而是在服务中实现。

        2
  •  0
  •   Anand    7 年前

    我想这就是我作为答案所做的,以防万一这可能会对我的情况有所帮助,这就是Web API中的简单Windows身份验证。我使用剑道-所以使用加载微调器使事情同步。

    // app.component.ts
      ngOnInit(): void {
      sessionStorage.clear();
      sessionStorage.setItem('requestedRoute', window.location.pathname);
      this._router.navigateByUrl(AppSettings.AuthRoute, {skipLocationChange: true});
    }
    
    
     // AuthRoute -> auth.component.ts
     @Component({
     selector: 'app-auth',
    template: `
    <div *ngIf="isAuthenticating()" class="k-i-loading"></div>
    <div style="padding:20px"><h4>Authenticating...</h4><div>
    <div kendoDialogContainer></div>
    `,
    styles: []
    })
       ngOnInit() {
    this._authService.authenticate().subscribe((user: User) => {
      if (user !== undefined) {
        user.isAuthencated = true;
        sessionStorage.setItem('currentuser', JSON.stringify(user));
        this._router.navigateByUrl(sessionStorage.getItem('requestedRoute'));
      }
     });
    }
    
    public isAuthenticating() {
      return this._authService.isAuthenticating;
    }
    
     //auth.service.ts
     public isAuthenticating = true; // loading spinner
    
     constructor(private _http: HttpClient, private _trace: TraceService) { }
    
     public  authenticate(): Observable<User> {
     this.isAuthenticating = true;
     return this._http.get<User>(AppSettings.AuthUrl, {withCredentials: true})
                        .catch<any, User>((e, u) => this._trace.handleAuthError(e))
                        .catch<any, User>(this._trace.handleError('GET ' + AppSettings.AuthUrl, []))
                        .finally(() => this.isAuthenticating = false);
    }
    
      //auth.guard.ts
      public canActivate(): Observable<boolean> | boolean {
      const user = <User>JSON.parse(sessionStorage.getItem('currentuser'));
      if (user !== null && user.isAuthencated) {
        return true;
      } else {
      this._router.navigateByUrl(AppSettings.NotAuthenticatedRoute);
      return false;
     }
    }