使用 MSAL Guard 来保护路由

MSAL Angular 提供 MsalGuard一个类,可用于保护路由,并在访问受保护路由之前要求进行身份验证。 本文档提供有关使用 MsalGuard时配置和注意事项的详细信息。

MsalGuard 是一个方便类,你可以使用它改善用户体验,但不应依赖它的安全性。 攻击者可能会绕过客户端防护,应确保服务器不会返回用户不应访问的任何数据。

你可能还需要一个满足特定需求的路由守卫。 如果 MsalGuard 无法满足所有这些需求,我们建议你编写自己的防护。

配置

app.module.tsapp-routing.module.ts中配置MsalGuard

可以在 app.module.ts 中将 MsalGuard 连同其配置一起添加到应用程序中,作为提供程序。 这些导入项引入了一个 MSAL 实例,以及两个 Angular 专用的配置对象。 第二个参数是一个MsalGuardConfiguration对象,该对象包含可选interactionTypeauthRequest和可选loginFailedRoute值。

MsalGuard然后,它用于保护app-routing.module.ts中的路由。 下面的代码示例演示了如何将 MsalGuard 添加到 Profile 路由中。 保护 Profile 路由意味着,即使用户未使用 Login 按钮登录,如果他们尝试访问 Profile 路由或单击 Profile 该按钮, MsalGuard 则会在显示 Profile 页面之前提示用户通过弹出窗口或重定向进行身份验证。

配置可能如下所示。 有关为应用配置 MSAL Angular 的其他方法,请参阅我们的 配置文档 ,并参阅以下部分,了解有关 MsalConfiguration 用于路由的对象和接口的更多详细信息。

// app.module.ts
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http";
import { MsalModule, MsalRedirectComponent, MsalGuard } from '@azure/msal-angular'; // Import MsalInterceptor
import { InteractionType, PublicClientApplication } from '@azure/msal-browser';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
    declarations: [
        AppComponent,
    ],
    imports: [
        MsalModule.forRoot( new PublicClientApplication({
            // MSAL Configuration
        }), {
            // MSAL Guard Configuration
            interactionType: InteractionType.Redirect,
            authRequest: {
                scopes: ['user.read']
            },
            loginFailedRoute: '/login-failed'
        }, {
            // MSAL Interceptor Configurations
        }),
        AppRoutingModule
    ],
    providers: [
        // ...
        MsalGuard
    ],
    bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule { }
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ProfileComponent } from './profile/profile.component';
import { MsalGuard } from '@azure/msal-angular';

const routes: Routes = [
    {
        path: 'profile',
        component: ProfileComponent,
        canActivate: [MsalGuard]
    },
    {
        path: '',
        component: HomeComponent
    },
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule { }

交互类型

设置交互类型可确定 MsalGuard 将如何以交互方式提示登录。 InteractionType可从@azure/msal-browser导入,并设置为PopupRedirect

可选 authRequest

可选 authRequest 是不需要的高级功能。 但是,我们建议在 MsalGuardConfiguration 上使用 scopes 设置 authRequest,以便提前就这些范围获得同意。 如果未事先获得对 scopes 的同意,则可以分阶段获取权限范围。 这可能会导致多次向应用用户显示同意对话。

预先同意这些范围这一做法已在上面的代码示例以及我们的示例中进行了演示。

可在以下位置找到请求对象的所有可能参数: PopupRequestRedirectRequest

登录失败路由

可在 MsalGuardConfiguration 上设置 loginFailedRoute 字符串。 如果需要登录但登录失败,MsalGuard 将重定向到此路由。

有关在 配置应用路由模块中实现它的示例,请参阅 Angular 示例。

请注意,对于使用 CanLoad 接口的 Angular 9 应用程序,由于基类型差异,失败时进行重定向不可用。

Interfaces

除了 canActivate 之外,MsalGuard 还实现了 canActivateChildcanLoad,并且可以将这些内容添加到 app-routing.module.ts 中的路由定义中。 你可以在我们的旧版 MSAL Angular v2 Angular 11 示例应用程序以及下文中看到这些用法。 有关接口的详细信息,请参阅 Angular 文档

const routes: Routes = [
    {
        path: 'profile',
        canActivateChild: [MsalGuard],
        children: [
        {
            path: '',
            component: ProfileComponent
        },
        {
            path: 'detail',
            component: DetailComponent
        }
        ]
    },
    { 
        path: 'lazyLoad', 
        loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule),
        canLoad: [MsalGuard]
    },
];

使用 MSAL Guard 时的注意事项

在主页中使用 MSAL Guard

如果您希望用户在访问应用程序时被提示登录,我们建议在初始页面上设置 MsalGuard。 我们不建议在 app.component.ts 中的 ngOnInit 里调用 login,因为这可能会导致重定向循环。

我们的其他建议取决于路由策略,可在以下部分中找到。

将 MSAL Guard 与路径路由配合使用

在 Angular 应用中使用 PathLocationStrategy 和重定向时,我们建议使用专用路由进行重定向,这有助于防止循环。 此路由也应该是你的 redirectUri,不应受到 MsalGuard 的保护

const routes: Routes = [
    {
        path: 'profile',
        component: ProfileComponent,
        canActivate: [MsalGuard]
    },
    {
        // Dedicated route for redirects
        path: 'auth', 
        component: MsalRedirectComponent
    },
    {
        path: '',
        component: HomeComponent
    }
];

要在用户访问你的应用时将其登录,使用 PathLocationStrategy 时,我们建议:

  • 在您的初始页面上设置 MsalGuard
  • redirectUri 设置为 'http://localhost:4200/auth'
  • 为路由添加 'auth' 路径,并将 MsalRedirectComponent 设置为组件(此路由不应受 MsalGuard 保护)
  • 确保 MsalRedirectComponent 已启动
  • 可选:如果你希望所有路由都受到保护,可将 MsalGuard 添加到所有路由中

我们的Angular 模块示例使用了PathLocationStrategy,并演示了如何使用MsalGuard保护路由。

将 MSAL Guard 与哈希路由配合使用

HashLocationStrategy与 Angular 应用一起使用时,我们强烈建议在/code中设置占位符路由(例如),以防止在Microsoft Entra ID在哈希中返回身份验证代码响应时触发 Angular 路由器,因为你可能在完成身份验证时可能会遇到问题,而无需这样做。 这些占位符路由不应受到 MsalGuard保护,不应指向触发交互或在页面加载时进行受保护的 API 调用的组件。

const routes: Routes = [
  {
    path: 'profile',
    component: ProfileComponent,
    canActivate: [MsalGuard]
  },
  {
    // Needed for hash routing
    path: 'code',
    component: HomeComponent
  },
  {
    path: '',
    component: HomeComponent
  }
];

MSAL 配置中的 redirectUri 也应设置为主页。

要在用户访问你的应用时将其登录,使用 HashLocationStrategy 时,我们建议:

  • 在您的初始页面上设置 MsalGuard
  • 未在占位符路由(例如 /code/error)上设置 MsalGuard
  • 确保 MsalRedirectComponent 已启动
  • (可选):如果您希望所有路由都受到保护,可将 MsalGuard 添加到其余所有路由中

请参阅我们的较旧的 MSAL Angular v2 Angular 11 示例,该示例使用 HashLocationStrategy,并演示如何使用 MsalGuard 保护路由。

从 msal-angular v1 到 v2 的变更

  • 配置MsalAngularConfiguration 已弃用,不再有效。 现在,MsalGuard 的配置是通过 MsalGuardConfiguration 进行的。
  • 接口MsalGuard 现在除 CanActivate 外,还实现了 CanActivateChildCanLoad。 有关更多详细信息,请参阅上面的 Interfaces 部分。
  • 失败时重定向MsalGuard 配置中现在有一个可配置的 loginFailedRoute。 有关 loginFailedRoute 的详细信息,请参阅上文相关部分。