首页 文章

Angular 4隐式流回调和路由器防护

提问于
浏览
13

在Angular 4中处理隐式流回调的最佳方法是什么?我希望Guard等到用户被重定向回到令牌并且在Guard返回true或false之前存储它,我在重定向回来检查令牌之前得到了拒绝访问路由几秒钟 . 有没有比我正在做的更好的方式来处理AuthGuard,所以在认证完成之前我没有得到拒绝访问?

如何让路由器保护等待重定向?

AppComponent

ngOnInit() {    

         //if there is a hash then the user is being redirected from the AuthServer with url params
         if (window.location.hash && !this.authService.isUserLoggedIn()) {     

          //check the url hash
          this.authService.authorizeCallback();

        }
        else if (!this.authService.isUserLoggedIn()) {         

          //try to authorize user if they aren't login
          this.authService.tryAuthorize();       

  }    
}

AuthSerivce

tryAuthorize() {
       //redirect to open id connect /authorize endpoint
        window.location.href = this.authConfigService.getSignInEndpoint();
    }

    authorizeCallback() {       

        let hash = window.location.hash.substr(1);

        let result: any = hash.split('&').reduce(function (result: any, item: string) {
            let parts = item.split('=');
            result[parts[0]] = parts[1];
            return result;
        }, {});


        if (result.error && result.error == 'access_denied') {
            this.navigationService.AccessDenied();
        }
        else {

            this.validateToken(result);
        }
    }


    isUserLoggedIn(): boolean {       
        let token = this.getAccessToken();

        //check if there is a token      
        if(token === undefined || token === null || token.trim() === '' )
        {
            //no token or token is expired;
            return false;
        }

        return true;
    }


    getAccessToken(): string {              

        let token = <string>this.storageService.get(this.accessTokenKey);


        if(token === undefined || token === null || token.trim() === '' )
        {
            return '';
        }

        return token;
    }

    resetAuthToken() {
        this.storageService.store(this.accessTokenKey, '');
    }

    validateToken(tokenResults: any) {        

        //TODO: add other validations         

        //reset the token
        this.resetAuthToken();

        if (tokenResults && tokenResults.access_token) {

            //store the token
            this.storageService.store(this.accessTokenKey, tokenResults.access_token);

            //navigate to clear the query string parameters
            this.navigationService.Home();

        }
        else {
            //navigate to Access Denied
            this.navigationService.AccessDenied();
        }

    }
}

AuthGuard

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot){

    var hasAccess = this.authService.isUserLoggedIn();        

    if(!hasAccess)
    {
        this.naviationService.AccessDenied();
        return false;
    }
     return true;    
  }

2 回答

  • 6

    如果您希望您的警卫等待异步任务,您需要更改您的AuthService以返回您想要等待的异步任务中所需的observable和emit值,在您的情况下为reduce() . 之后在守卫中订阅 . 通过这种方式,您可以让您的警卫等待任何异步任务 .

    AuthGuard

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot){
    
      this.authService.isUserLoggedIn().map(logged => {
            if (logged) {
                return true;
            } else {
                this.naviationService.AccessDenied();
                return false;
            }
        }).catch(() => {
            this.naviationService.AccessDenied();
            return Observable.of(false);
        });
      }
    }
    

    AuthService的一部分

    isUserLoggedIn(): Observable<boolean> {
        return new Observable((observer) => {
          let hash = window.location.hash.substr(1);
    
          let result: any = hash.split('&').reduce(function (result: any, item: string) {
            let parts = item.split('=');
            result[parts[0]] = parts[1];
    
            if (result.error && result.error == 'access_denied') {
              observer.next(false);
              observer.complete();
            }
            else {
              this.validateToken(result);
            }
            let token = this.getAccessToken();
    
            //check if there is a token      
            if(token === undefined || token === null || token.trim() === '' )
            {
              //no token or token is expired;
              observer.next(false);
              observer.complete();
            }
    
            observer.next(true);
            observer.complete();
          }, {});
        });
    }
    
  • 1

    CanActivate 方法可以返回 ObservablePromiseBoolean ,Angular将知道打开它并处理所有异步 . 在将完成/失败的 Observable 或已解析/拒绝的 Promise 返回到Angular路由器之前,您可以更改代码以检查必要的数据,并在该异步函数的作用下调用 this.naviationService.AccessDenied() .

相关问题