You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中Observable错误处理:AuthGuard 401异常拦截问题

AuthGuard未处理401错误导致无法跳转登录页

问题描述

创建AuthGuard时,期望未登录用户访问受保护路由时自动跳转到登录页,但实际出现错误且无任何跳转。后端在未检测到Auth Token时返回:

{"status":401,"message":"Auth Token Not found!"}

现有代码

AuthGuardService

export class AuthGuardService implements CanActivate {

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {

    return this.authService.checkLogin().pipe(
      map((data: HttpResponse) => {
        if (data.status == 200) {
          console.log("OUTPUT:", data)
          return true
        }
        else return false
      }),
    )

  }
}

AuthService的checkLogin方法

public checkLogin():Observable<HttpResponse> {

    return this.http.get<HttpResponse>('http://localhost:5000/auth/check-login', { withCredentials: true })

  }

问题分析

  1. HttpClient默认行为:Angular的HttpClient会将非2xx状态码的响应视为错误,直接进入错误流,不会执行map操作符中的逻辑,因此原代码无法处理401错误。
  2. 未获取完整HTTP响应:原get请求未设置observe: 'response'选项,返回的是响应体数据而非HttpResponse对象,导致data.status无法正确获取。

解决方案

步骤1:修改AuthService,获取完整HTTP响应

在get请求中添加observe: 'response'选项,确保能拿到包含状态码的HttpResponse对象:

import { HttpClient, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';

public checkLogin(): Observable<HttpResponse<any>> {
  return this.http.get<any>(
    'http://localhost:5000/auth/check-login', 
    { 
      withCredentials: true,
      observe: 'response' // 关键:获取完整的HTTP响应
    }
  );
}

步骤2:修改AuthGuard,处理错误并跳转登录页

使用catchError操作符捕获HTTP错误,跳转至登录页并返回false以阻止路由访问,同时可保存当前路由地址以便登录后跳转:

import { map, catchError } from 'rxjs/operators';
import { of } from 'rxjs';

export class AuthGuardService implements CanActivate {

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.authService.checkLogin().pipe(
      map((data: HttpResponse<any>) => {
        // 仅在200状态码时允许访问
        if (data.status === 200) {
          console.log("OUTPUT:", data);
          return true;
        }
        // 非200状态码(理论上不会走到这里,因为HttpClient会抛错)
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return false;
      }),
      catchError(() => {
        // 捕获401等所有HTTP错误,跳转登录页
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return of(false);
      })
    );
  }
}

关键说明

  • catchError会捕获所有HTTP错误(包括401),确保无论后端返回什么错误状态码,都能触发登录跳转。
  • queryParams: { returnUrl: state.url }保存当前用户试图访问的路由,登录成功后可跳回该页面,提升用户体验。
  • 修正了类型定义,使用HttpResponse<any>明确响应类型,避免类型错误。

内容的提问来源于stack exchange,提问作者Snake_Eyes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:01:07