Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角形路由器赢得';在http拦截器中导航_Angular_Typescript - Fatal编程技术网

Angular 角形路由器赢得';在http拦截器中导航

Angular 角形路由器赢得';在http拦截器中导航,angular,typescript,Angular,Typescript,如果用户未经身份验证或其令牌已过期,我将尝试将用户重定向到登录页面。我的拦截器工作正常,但角度路由器没有重定向它们。如果我使用window.location.href=“/login”,那么它可以正常工作,但显然这不是一种角度的方式,也会导致我的应用程序重新加载。 以下是我当前的http拦截器: import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent,

如果用户未经身份验证或其令牌已过期,我将尝试将用户重定向到登录页面。我的拦截器工作正常,但角度路由器没有重定向它们。如果我使用window.location.href=“/login”,那么它可以正常工作,但显然这不是一种角度的方式,也会导致我的应用程序重新加载。 以下是我当前的http拦截器:

import { Injectable } from '@angular/core';
import {
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../services/auth.service';
import { Router } from '@angular/router';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {

    constructor(private authService: AuthService, private router: Router ) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return this.authService.getSession().mergeMap(session => {
            if (session) {
                if (session.getIdToken().decodePayload().passwordExpired == 'true' && !this.router.url.includes('change-password')) {
                    // this navigation does not work
                    this.router.navigate(['/login/change-password'])
                } else if (request.url.includes(this.authService.awsUrl) || request.url.includes(this.authService.userUrl)) {
                    request = request.clone({
                        setHeaders: {
                            Authorization: `Bearer ${session.getIdToken().getJwtToken()}`
                        }
                    });
                }
                return next.handle(request);
            } else if (this.router.url.includes('login') || this.router.url.includes('provision')) {
                return next.handle(request);
            } else {
                //this navigation also does not work
                this.router.navigate(['/login']);
                return Observable.throw('token is not valid');
            }
        });
    }
}
从'@angular/core'导入{Injectable};
进口{
HttpRequest,
HttpHandler,
HttpEvent,
http拦截器
}来自“@angular/common/http”;
从“rxjs/Observable”导入{Observable};
从“../services/auth.service”导入{AuthService};
从'@angular/Router'导入{Router};
@可注射()
导出类TokenInterceptor实现HttpInterceptor{
构造函数(私有authService:authService,私有路由器:路由器){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回此.authService.getSession().mergeMap(会话=>{
国际单项体育联合会(届会){
if(session.getIdToken().decodePayload().passwordExpired=='true'&&!this.router.url.includes('change-password')){
//此导航不起作用
this.router.navigate(['/login/change password'])
}else if(request.url.includes(this.authService.awsUrl)| | request.url.includes(this.authService.userUrl)){
request=request.clone({
集合标题:{
授权:`Bearer${session.getIdToken().getJwtToken()}`
}
});
}
下一步返回。处理(请求);
}else if(this.router.url.includes('login')| | this.router.url.includes('provision')){
下一步返回。处理(请求);
}否则{
//此导航也不起作用
this.router.navigate(['/login']);
return Observable.throw('token无效');
}
});
}
}

我还尝试将导航放在auth服务的方法中,但这也不起作用。我做错什么了吗?或者我只是错过了一些导致路由器挂起的小东西?如果这有什么不同的话,我会选择angular v6。

在我看来,这个逻辑应该完全从拦截器中删除

角路由器具有内置保护选项,可保护路由。请参阅以查看不同的防护类型

通过这种方式,您可以在允许用户查看路由之前检查用户身份验证,这是根据您的场景尝试重新路由的逻辑所在

一旦用户获得授权,他们将通过所需的路径进行API调用,然后通过拦截器返回进行调用的组件

总之,

  • 在允许用户查看路由之前,应使用身份验证卫士对用户进行验证和授权。如果用户因任何原因未经授权,请重新路由到相应的路由
  • 在HTTP调用离开应用程序之前以及首次返回应用程序时,应使用拦截器修改HTTP调用。在这里,您可以设置头,通过env变量修改端点,等等

一些进一步的信息,以帮助将来偶然发现这个问题的人。我从接受的答案中得到了建议,并将重定向逻辑移到了auth-guard和error-interceptor中,但即使在重构之后,
router.navigate(['/login'])
仍然不起作用。我最终意识到路由器被挂起是因为我的身份验证守卫在用户未经身份验证的情况下从未解析。使防护解决后,重定向工作正常。

如果要放置路由器导航,则必须将此代码放置在tap功能中, 例如:

return next.handle(tokenizedReq).pipe(
        tap({
          error: (res) => {    
            this.route.navigate(['/error'])
            console.log("tap, error", res);
          }
        }),
        catchError(this.errorHandler)  // this.errorHandler is a function
      );

您在控制台中是否遇到任何类型的错误可以在调试模式下一步一步地进行并确认您到达了if部分?控制台中没有错误,我已经确认它正在进入if部分。我当前的代码是window.location.href,而不是router.navigate,这是可行的,但我不喜欢它使我的应用程序重新加载,这显然不是最佳做法。你是从路由器解析内部调用此请求吗?你能启用路由跟踪并粘贴日志吗
RouterModule.forRoot(routes,{enableTracing:true})
同意这一点,非常有效,特别是因为他担心角度问题。如果您已经打开了一条路由,请保持选项卡打开,稍后再回来,在这个拦截器将带您返回
/login
页面的同时被取消授权。但是我也认为这不应该在拦截器中实现,而是额外的。非常有效的一点。我将重构我的应用程序,使其在一个防护中重定向,而不是在这个拦截器中重定向。如果一个用户正在进行身份验证,坐在页面上,并且他们的令牌过期了,该怎么办?在这种情况下,我似乎必须从拦截器重定向,但如果我尝试从错误拦截器导航,则可能不会发生此问题。从拦截器路由是完全可能的,只应在必要时轻轻使用。您可以查看401的响应类型,如果未经授权,可以重定向,但核心身份验证逻辑应该在保护锁定路由的身份验证保护中。阿门,救了我一天!