typescript 如何重定向到 Angular 5 中 401 响应的登录页面?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51019619/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:29:47  来源:igfitidea点击:

How can I redirect to login page on 401 response in Angular 5?

angulartypescriptoauth-2.0interceptor

提问by ilMattion

I'm working on a Angular 5 application using OAuth2 implicit flow.

我正在使用 OAuth2 隐式流处理 Angular 5 应用程序。

I have services that perform HTTP calls, following one example of my services:

我有执行 HTTP 调用的服务,以下是我的一个服务示例:

@Injectable()
export class MyService {

  constructor(public http: HttpClient) { }

  public getAll(): Observable<Persona[]> {
    return this.http.get<Persona[]>("http://mywebservice/persone");
  }
}

I'm using interceptors for authorization and add custom attributes. Following my auth interceptor:

我正在使用拦截器进行授权并添加自定义属性。按照我的身份验证拦截器:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from "rxjs";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {

  }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let accessToken = sessionStorage.getItem("access_token");
    if(accessToken)
    {
        request = request.clone({
        setHeaders: {
            Authorization: `Bearer ${accessToken}`
        }
        });
    }

    return next.handle(request);
  }
}

And following how I consume my services:

并遵循我如何使用我的服务:

public myMethod() {
    this.myService.getAll().subscribe(
        result => {
            console.log(result);
        }, error => {
            // I don't want add redirection there...
            console.error(error);
        });
}

Now my need is that when any HTTP call receive 401 result, the application redirects the user to login page.

现在我需要的是,当任何 HTTP 调用收到 401 结果时,应用程序将用户重定向到登录页面。

How can I obtain this result without code duplication?

如何在不重复代码的情况下获得此结果?

Thank you a lot

非常感谢

回答by ilMattion

I resolved my problem changing my interceptor like following:

我解决了更改拦截器的问题,如下所示:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {

  }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let accessToken = sessionStorage.getItem("access_token");
    if(accessToken)
    {
        request = request.clone({
        setHeaders: {
            Authorization: `Bearer ${accessToken}`
        }
        });
    }

    return next.handle(request).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        if (err.status === 401) {
            this.router.navigate(['login']);
        }
      }
    });
  }
}

I found the solution there: https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

我在那里找到了解决方案:https: //medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

回答by Jalaleddin Hosseini

Only to support new readers, notice that in angular 7 you should use pipe() instead of do() or catch():

只是为了支持新读者,请注意,在 angular 7 中,您应该使用 pipe() 而不是 do() 或 catch():

return next.handle(request).pipe(catchError(err => {
    if (err.status === 401) {
        MyComponent.logout();
    }
    const error = err.error.message || err.statusText;
        return throwError(error);
}));

回答by Siro

Attach the error handling to the common request handler:

将错误处理附加到公共请求处理程序:

return next.handle(request).catch(err => {
    if (err.status === 401) {
         // Redirect here
    }
}

You can import the router directly in the interceptor, but the proper way to do it is to create an authentication service or similar that imports the router and call it to do the redirection

您可以直接在拦截器中导入路由器,但正确的方法是创建一个身份验证服务或类似的导入路由器并调用它来进行重定向