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

Angular 4隐式流回调和路由器保护,angular,angular4-router,Angular,Angular4 Router,在Angular 4中处理隐式流回调的最佳方法是什么?我希望警卫等待,直到用户被重定向回令牌,并且在警卫返回true或false之前,它被存储。在我被重定向回检查令牌之前,我将获得拒绝访问的路由几秒钟。有没有比我现在做的更好的方法来处理AuthGuard,这样我就不会在身份验证完成之前拒绝访问 如何使路由器防护等待重定向 AppComponent ngOnInit() { //if there is a hash then the user is being

在Angular 4中处理隐式流回调的最佳方法是什么?我希望警卫等待,直到用户被重定向回令牌,并且在警卫返回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();
        }

    }
}

CanActivate
方法可以返回一个
可观察的
承诺
布尔值
,Angular将知道如何展开它并异步处理所有内容。您可以更改代码以检查必要的数据,然后将已完成/失败的
可观察的
或已解决/拒绝的
承诺
返回给角度路由器,并调用
this.naviationService.AccessDenied()
作为该异步函数的结果。

如果希望警卫等待异步任务,则需要更改AuthService以返回要等待的异步任务内部所需的可观察值并发出值,在本例中为reduce()。之后,在guard中订阅。通过这种方式,您可以让您的守卫等待任何异步任务

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();
      }, {});
    });
} 
isUserLoggedIn():可观察{
返回新的可观察对象((观察者)=>{
设hash=window.location.hash.substr(1);
let result:any=hash.split('&').reduce(函数(结果:any,项:string){
让parts=item.split('=');
结果[部分[0]]=部分[1];
if(result.error&&result.error==“拒绝访问”){
观察者:下一个(假);
observer.complete();
}
否则{
这个.validateToken(结果);
}
让token=this.getAccessToken();
//检查是否有代币
if(token==未定义的| | token===null | | | token.trim()==='')
{
//没有令牌或令牌过期;
观察者:下一个(假);
observer.complete();
}
观察者:下一个(正确);
observer.complete();
}, {});
});
} 

从另一个/授权服务器重定向时,这是如何工作的?我了解使用数据api的可观察对象,但不太了解重定向?您能否提供一个代码示例?谢谢。基本上是在Angular加载路由和组件之前调用您的
AuthGuard
。在当前实现中,您的
CanActivate
立即返回false并导航到
AccessDenied
。它看起来像是使用该路由或外部重定向设置的内容,然后重新加载页面,其中再次触发
AuthGuard
,并返回true。根据auth服务器的实现,我可以看出在哪些地方很难消除这种情况。您可能希望让窗口等待重定向,或者检查
resolve
router方法…以便在组件实际加载之前获取其数据。是的,应用程序内组件ngOnInit()重定向到auth服务器或调用tryAuthorize,这将使令牌有效,然后重定向到我拥有AuthGuard的主路由,Guard所做的只是检查它们是否已登录,如果令牌存在于存储中,则返回true或false。这似乎工作正常,但我想可能与另一个问题有关使用可见光。当我尝试在Obserable中使用注入服务时,比如isUserLoggedIn方法中的this.logger.log,它会在Obserable.prototype方法的observer.js中抛出错误。\u trySubscribe=function(sink){try{return this.\u subscribe(sink);}catch(err){sink.syncErrorSprown=true;sink.syncErrorValue=err;sink.error(err);};它在构造函数中注册,在可观察范围之外工作,但不在可观察范围之内。如果我尝试使用注入式服务,我实际上只会在可观察范围内出错。使用reduce函数之外的逻辑,它会工作得更好。我想我需要了解更多有关创建可观察范围的信息,但我正在了解observer。下一步返回值并observer.complete到complete,我还没有用过,但我想我现在明白了。
 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();
      }, {});
    });
}