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