ADAL5 Angular未授权用户URL循环,需跳转至自定义错误页
解决Adal Angular5未授权用户循环跳转问题
我来帮你搞定这个URL循环跳转的问题!核心原因是你的Guard只判断了用户是否已认证,但没处理用户已登录但无应用权限的情况——当Azure AD返回access_denied(对应AADSTS50105错误)时,你的代码依然会触发登录跳转,导致AAD和你的应用之间反复重定向。
问题根源分析
当用户已登录但未被分配到应用的授权组/角色时,Azure AD会回调到你的应用,携带error=access_denied和error_description=AADSTS50105参数。但当前的AdalGuard只检查userInfo.authenticated:
- 如果此时
authenticated为false(Adal可能因为错误标记用户未认证),代码会调用login()再次跳转AAD; - AAD发现用户已登录但无权限,再次回调应用,形成循环。
解决方案:在Guard中处理访问拒绝错误
修改你的adal.guard.ts,添加对AAD错误参数的检测,当识别到access_denied时,直接跳转到自定义401错误页,避免触发登录跳转:
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { Adal5Service } from 'adal-angular5'; import { environment } from '../environments/environment'; import { Router } from '@angular/router'; @Injectable() export class AdalGuard implements CanActivate { constructor(private adal5Service: Adal5Service, private router: Router) { // 建议:把Adal初始化移到AppModule的APP_INITIALIZER中,避免每次Guard激活都重复初始化 console.log("location below: "); if (location) console.log(location); else console.log("some falsy value"); this.adal5Service.init({ ...environment.ssoConfig, redirectUri: location.protocol + '//' + location.host + location.pathname }); } canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { if (!environment.production) return true; this.Callback(); // 解析URL Hash中的错误参数 const hashParams = new URLSearchParams(window.location.hash.slice(1)); const error = hashParams.get('error'); const errorDescription = hashParams.get('error_description'); // 识别Azure AD的"用户未分配应用角色"错误 const isAccessDenied = error === 'access_denied' && errorDescription?.includes('AADSTS50105'); if (isAccessDenied) { // 清除Hash中的错误参数,避免页面刷新后再次触发逻辑 window.history.replaceState({}, document.title, window.location.pathname); // 跳转到自定义401错误页 this.router.navigate(['error/401']); return false; } if (!this.adal5Service.userInfo.authenticated) { this.LogIn(); return false; } else { return true; } } Callback() { this.adal5Service.handleWindowCallback(); } LogIn() { this.adal5Service.login(); } }
关键注意事项
错误页路由需排除Guard保护
确保你的401错误页路由不使用AdalGuard,否则会再次触发认证逻辑,导致新的循环:// app-routing.module.ts const routes: Routes = [ { path: '', component: HomeComponent, canActivate: [AdalGuard] }, { path: 'error/401', component: UnauthorizedComponent }, // 这里不要加canActivate // 其他业务路由... ];优化Adal初始化逻辑
把Adal的init从Guard构造函数移到APP_INITIALIZER中,确保初始化只执行一次:// app.module.ts import { APP_INITIALIZER } from '@angular/core'; import { Adal5Service } from 'adal-angular5'; import { environment } from '../environments/environment'; // 定义初始化工厂函数 export function adalInitializer(adalService: Adal5Service) { return () => { adalService.init({ ...environment.ssoConfig, redirectUri: window.location.protocol + '//' + window.location.host + window.location.pathname }); }; } @NgModule({ // ...其他配置 providers: [ Adal5Service, { provide: APP_INITIALIZER, useFactory: adalInitializer, deps: [Adal5Service], multi: true }, AdalGuard ] }) export class AppModule { }
这样修改后,未授权用户会被直接引导到自定义401错误页,彻底解决循环跳转问题。
内容的提问来源于stack exchange,提问作者Vista
相关产品推荐
相关产品推荐

