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

Angular+adal.js会话过期时如何重定向至登录页(解决CORS报错)

解决Adal.js会话过期时CORS报错并自动重定向到登录页的问题

问题分析

你遇到的CORS错误根源在于:会话过期后,Adal.js默认会尝试通过跨域请求去获取新令牌,但Azure AD的授权端点本身不支持CORS,导致浏览器拦截这个请求并抛出错误。要解决这个问题,我们需要让Adal.js在检测到令牌过期时直接触发登录页重定向,而非发起这个无效的跨域请求。

解决方案步骤

1. 调整Adal核心配置参数

你的现有配置已经具备基础框架,我们需要优化几个关键参数,并补充主动处理逻辑:

  • 保留expireOffsetSeconds: 600:提前10分钟检测令牌过期,给重定向流程预留缓冲时间
  • 将navigateToLoginRequestUrl设为true:登录成功后自动跳回用户之前访问的页面(如果不需要该行为可保持false)
  • 核心思路:通过Adal的服务方法主动触发登录,替代默认的跨域令牌请求逻辑

2. 用路由守卫提前拦截未授权访问

在Angular的CanActivate路由守卫中,提前检查用户认证状态,一旦发现会话过期,直接触发登录重定向:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AdalService } from 'adal-angular';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private adalService: AdalService, private router: Router) {}

  canActivate(): boolean {
    const isAuthenticated = this.adalService.userInfo.authenticated;
    
    // 直接判断是否已认证
    if (!isAuthenticated) {
      this.adalService.login();
      return false;
    }

    // 额外检查令牌是否即将过期(基于你配置的expireOffsetSeconds)
    const tokenExpiration = this.adalService.getTokenExpiration(this.adalService.config.clientId);
    const now = new Date().getTime();
    if (tokenExpiration - now < this.adalService.config.expireOffsetSeconds * 1000) {
      this.adalService.login();
      return false;
    }
    
    return true;
  }
}

3. 拦截API请求的401错误

如果用户在会话过期后发起API请求,服务器会返回401状态码,此时在HTTP拦截器中捕获该错误并触发登录:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AdalService } from 'adal-angular';

@Injectable()
export class AdalInterceptor implements HttpInterceptor {
  constructor(private adalService: AdalService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 给API请求附加Bearer令牌
    const token = this.adalService.getToken(this.adalService.config.clientId);
    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`
        }
      });
    }

    return next.handle(request).pipe(
      catchError((error: HttpErrorResponse) => {
        // 捕获401错误,清理缓存并跳转登录
        if (error.status === 401) {
          this.adalService.clearCache();
          this.adalService.login();
        }
        return throwError(error);
      })
    );
  }
}

4. 更新后的Adal配置代码

调整后的配置保留原有核心项,确保端点映射正确:

export function getAdalConfig() {
  return {
    tenant: 'de08ccD7-19b9-427d-9fe8-edf254300ca7',
    clientId: '828002a4-149f-478c-a318-933ad52ererf',
    redirectUri: window.location.origin,
    endpoints: {
      "https://xxx.azurewebsites.net/api/":"828002a4-149f-478c-a318-233456"
    },
    navigateToLoginRequestUrl: true, // 登录后自动返回原请求页面
    cacheLocation: 'localStorage',
    expireOffsetSeconds: 600
  };
}

关键说明

  • 主动调用adalService.login()会直接重定向到Azure AD登录页,完全规避了Adal默认发起的跨域请求,从根源上解决CORS报错
  • 路由守卫实现了"前置拦截",在用户访问受保护路由时就提前处理过期情况,提升体验
  • HTTP拦截器覆盖了"已进入页面后发起请求"的场景,确保所有未授权请求都会触发登录跳转

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:05:59