Angular单页应用程式 (SPA)+Azure AD重新导向登入
一.app.module.ts中设定应用程式
1.将MSAL Angular相关设置封装为auth.module.ts
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MsalGuard, MsalBroadcastService, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MsalGuardConfiguration, MsalRedirectComponent } from '@azure/msal-angular'; import { IPublicClientApplication, PublicClientApplication, InteractionType } from '@azure/msal-browser'; import { LogLevel, Configuration, BrowserCacheLocation } from '@azure/msal-browser'; const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; export function MSALInstanceFactory(): IPublicClientApplication { return new PublicClientApplication( { auth: { clientId: '', // 应用clientId authority: 'https://login.microsoftonline.com/common',, redirectUri: '', }, cache: { cacheLocation: BrowserCacheLocation.LocalStorage, // LocalStorage缓存 storeAuthStateInCookie: isIE, // IE11或Edge上遇到问题 }, }); } export function MSALGuardConfigFactory(): MsalGuardConfiguration { return { interactionType: InteractionType.Redirect, }; } @NgModule({ declarations: [], imports: [ MsalModule, CommonModule ], providers: [ { provide: MSAL_INSTANCE, useFactory: MSALInstanceFactory }, { provide: MSAL_GUARD_CONFIG, useFactory: MSALGuardConfigFactory }, MsalService, MsalGuard, MsalBroadcastService, ], }) export class AuthModule { }
2.app.module.ts引入auth.module.ts;同时引入MsalRedirectComponent
重新导向组件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import { AppComponent } from './app.component'; import { AuthModule } from './auth/auth.module'; import {MsalRedirectComponent } from '@azure/msal-angular';//导入处理重新导向的组件 @NgModule({ declarations: [ ... AppComponent, ], imports: [ ... AuthModule, ], bootstrap: [AppComponent,MsalRedirectComponent], })
3.將 <app-redirect>
选取器新增至 src/index.html。 此选取器是由 MsalRedirectComponent
使用
4.登录;订阅LOGIN_SUCCESS
事件。 可从使用重新导向的成功登入存取結果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import { Component, OnInit } from '@angular/core'; import { MsalBroadcastService, MsalService } from '@azure/msal-angular'; import { AuthenticationResult, EventMessage, EventType, InteractionStatus } from '@azure/msal-browser'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-home-page', templateUrl: './home-page.component.html', styleUrls: ['./home-page.component.scss'] }) export class HomePageComponent implements OnInit { private readonly _destroying$ = new Subject<void>(); username: string | undefined; constructor( private authService: MsalService, private msalBroadcastService: MsalBroadcastService ) { } ngOnInit(): void { this.msalBroadcastService.msalSubject$ .pipe( filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS), takeUntil(this._destroying$) ) .subscribe((result: EventMessage) => { const payload = result.payload as AuthenticationResult; this.authService.instance.setActiveAccount(payload.account) this.setLoginDisplay(); }); this.setLoginDisplay(); } setLoginDisplay(){ if(this.authService.instance.getAllAccounts().length > 0){ this.username = this.authService.instance.getAllAccounts()[0].name; } } login(){ this.authService.loginRedirect(); } logout() { this.authService.logoutRedirect(); } }
5.根据重新导向的成功登入結果定义路由守卫
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import { MsalService } from '@azure/msal-angular'; import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; import { concatMap, catchError, map } from 'rxjs/operators'; import { Observable, of } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( private authService: MsalService, ) { } canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.authService.handleRedirectObservable() .pipe( concatMap(() => { if (!this.authService.instance.getAllAccounts().length) { this.authService.loginRedirect(); return of(false); } return of(true); }), catchError(() =>{ return of(false) } ) ); } }