Angular 路由与 Msal Azure AD 集成
Angular routing with Msal Azure AD integration
我在 Angular 13,使用 MSAL 与 Azure AD 集成。我的问题是一旦用户成功登录,logincomponent 就不会显示。但是,当我刷新页面时,会显示登录组件。如何让登录组件在用户登录后立即显示。
在实现调试时,在 AuthGaurd 启动时登录时,即使登录成功,此 this.msalsvc.instance.getActiveAccount() returns 仍为 null
这是我的应用路由,
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth-guard.guard';
import { LoginComponent } from './components/login/login/login.component';
import { TestComponent } from './components/test/test.component';
import { RoleGuard } from './route-guard.guard';
const routes: Routes =[
{path: '', component: TestComponent, canActivate: [AuthGuard]}
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
这是我的app.component.html
<app-header></app-header>
<div *ngIf="IsLoggedIn()">
<h3>Welcome {{userName}}</h3>
<h3>Your Assigned role: {{userRole}}</h3>
</div>
<div *ngIf="!IsLoggedIn()">
<h3>You are NOT logged in</h3>
</div>
<router-outlet></router-outlet>
<app-footer></app-footer>
这是 Auth Guard 的代码
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot, UrlTree } from '@angular/router';
import { MsalService } from '@azure/msal-angular';
import { map, Observable, Subscription } from 'rxjs';
import { CommonService } from './services/common-service.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate{
constructor(private msalsvc : MsalService){
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
console.log('Hi there, ');
if(this.msalsvc.instance.getActiveAccount() == null){
return false;
}
return true;
}
}
这是添加登录方法的普通服务
import { Injectable } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
import { AuthenticationResult } from '@azure/msal-browser';
import { observable, Observable, Subject,of} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CommonService {
//private loggedIn : boolean = false;
private subject = new Subject<any>();
constructor(private authService: MsalService) {
console.info('Common service is created');
}
login() {
this.authService.loginPopup()
.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
this.updateLoginNotification(true);
});
}
isLoggedIn(): boolean {
return this.authService.instance.getActiveAccount() != null
}
isAsyncLoggedIn():Observable<boolean>{
return of(this.authService.instance.getActiveAccount() !=null);
}
onLoginCheck(): Observable<boolean>{
return this.subject.asObservable();
}
getName():any{
this.getRole();
return this.authService.instance.getActiveAccount()?.name;
}
getRole():any{
return (this.authService.instance.getActiveAccount()?.idTokenClaims as any).roles;
}
updateLoginNotification(item: any) {
this.subject.next(item);
}
}
调用 login()
并确保它成功完成后,使用 Router
服务导航到正确的路径。这将导致身份验证守卫在登录后触发。
为了确保登录完成,您应该return在login()
函数中创建的observable。
在common.service.ts中:
login(): Observable<AuthenticationResult> {
const observable = this.authService.loginPopup();
observable.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
this.updateLoginNotification(true);
});
return observable;
}
现在,在调用 login()
后,您可以在 登录 后路由到正确的路径。
在app.component.ts中:
constructor(private router: Router, private loginService: LoginService) {}
login() {
const obs = this.loginService.login();
obs.subscribe((result) => {
//Check that the login was successful here
const success = true;
if (success) this.router.navigate(['yourPathHere']);
});
}
现在您知道用户在尝试加载页面之前已登录。 auth guard 只是作为一种预防措施存在,例如当用户使用 url.
手动导航时
我在 Angular 13,使用 MSAL 与 Azure AD 集成。我的问题是一旦用户成功登录,logincomponent 就不会显示。但是,当我刷新页面时,会显示登录组件。如何让登录组件在用户登录后立即显示。
在实现调试时,在 AuthGaurd 启动时登录时,即使登录成功,此 this.msalsvc.instance.getActiveAccount() returns 仍为 null
这是我的应用路由,
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth-guard.guard';
import { LoginComponent } from './components/login/login/login.component';
import { TestComponent } from './components/test/test.component';
import { RoleGuard } from './route-guard.guard';
const routes: Routes =[
{path: '', component: TestComponent, canActivate: [AuthGuard]}
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
这是我的app.component.html
<app-header></app-header>
<div *ngIf="IsLoggedIn()">
<h3>Welcome {{userName}}</h3>
<h3>Your Assigned role: {{userRole}}</h3>
</div>
<div *ngIf="!IsLoggedIn()">
<h3>You are NOT logged in</h3>
</div>
<router-outlet></router-outlet>
<app-footer></app-footer>
这是 Auth Guard 的代码
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot, UrlTree } from '@angular/router';
import { MsalService } from '@azure/msal-angular';
import { map, Observable, Subscription } from 'rxjs';
import { CommonService } from './services/common-service.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate{
constructor(private msalsvc : MsalService){
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
console.log('Hi there, ');
if(this.msalsvc.instance.getActiveAccount() == null){
return false;
}
return true;
}
}
这是添加登录方法的普通服务
import { Injectable } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
import { AuthenticationResult } from '@azure/msal-browser';
import { observable, Observable, Subject,of} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CommonService {
//private loggedIn : boolean = false;
private subject = new Subject<any>();
constructor(private authService: MsalService) {
console.info('Common service is created');
}
login() {
this.authService.loginPopup()
.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
this.updateLoginNotification(true);
});
}
isLoggedIn(): boolean {
return this.authService.instance.getActiveAccount() != null
}
isAsyncLoggedIn():Observable<boolean>{
return of(this.authService.instance.getActiveAccount() !=null);
}
onLoginCheck(): Observable<boolean>{
return this.subject.asObservable();
}
getName():any{
this.getRole();
return this.authService.instance.getActiveAccount()?.name;
}
getRole():any{
return (this.authService.instance.getActiveAccount()?.idTokenClaims as any).roles;
}
updateLoginNotification(item: any) {
this.subject.next(item);
}
}
调用 login()
并确保它成功完成后,使用 Router
服务导航到正确的路径。这将导致身份验证守卫在登录后触发。
为了确保登录完成,您应该return在login()
函数中创建的observable。
在common.service.ts中:
login(): Observable<AuthenticationResult> {
const observable = this.authService.loginPopup();
observable.subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
this.updateLoginNotification(true);
});
return observable;
}
现在,在调用 login()
后,您可以在 登录 后路由到正确的路径。
在app.component.ts中:
constructor(private router: Router, private loginService: LoginService) {}
login() {
const obs = this.loginService.login();
obs.subscribe((result) => {
//Check that the login was successful here
const success = true;
if (success) this.router.navigate(['yourPathHere']);
});
}
现在您知道用户在尝试加载页面之前已登录。 auth guard 只是作为一种预防措施存在,例如当用户使用 url.
手动导航时