[英]where can be stored user info in .net core API project with angular
[英]Problem with getting AD user info inside angular from .net core
我的应用程序由两个独立的项目组成:一个.NET 核心后端和一个Angular前端。
我已成功添加 windows AD 身份验证,并且我在我的 Angular 应用程序中获取用户信息,但仅在刷新页面后。
在第一页打开时,我的用户是 null
ERROR TypeError: Cannot read property 'name' of null
刷新后,我可以获取用户信息。 实际发生了什么,我该如何解决这个问题?
public Task < AdUser > GetAdUser(Guid guid) {
return Task.Run(() => {
try {
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal principal = new UserPrincipal(context);
if (context != null) {
principal = UserPrincipal.FindByIdentity(context, IdentityType.Guid,
guid.ToString());
}
return AdUser.CastToAdUser(principal);
} catch (Exception ex) {
throw new Exception("Error retrieving AD User", ex);
}
});
}
getCurrentUser() {
return this.http.get(this.apiUrl + '/identity/GetAdUser', { withCredentials: true });
}
this.identityService.getCurrentUser()
.subscribe(res => {
localStorage.setItem('user', JSON.stringify(res));
});
user = JSON.parse(localStorage.getItem('user'));
最后,我在顶部导航组件中获取用户数据,因为我需要在其中显示名字和姓氏。
编辑:添加了新代码
const appRoutes: Routes = [
{
path: 'home',
component: HomeComponent,
data: { title: 'Home' },
canActivate: [AuthGuardService]
},
{
path: 'history',
component: HistoryComponent,
data: { title: 'History' }
},
{
path: '404',
component: NotFoundErrorComponent,
data: { title: 'Error 404' }
},
{
path: '',
component: HomeComponent,
pathMatch: 'full'
},
{
path: '**',
redirectTo: '/404',
pathMatch: 'full',
data: { title: 'Error 404' }
}
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'Home';
constructor(private titleService: Title,
private router: Router,
private activatedRoute: ActivatedRoute { }
ngOnInit() {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route) => {
while (route.firstChild) { route = route.firstChild; }
return route;
}),
filter((route) => route.outlet === 'primary'),
mergeMap((route) => route.data))
.subscribe((event) => this.titleService.setTitle(event.title));
}
}
export class TopNavigationComponent implements OnInit {
constructor(private router: Router) { }
user;
ngOnInit() {
this.user = JSON.parse(localStorage.getItem('user'));
}
}
编辑:最终解决方案
const appRoutes: Routes = [
{
path: '',
component: TopNavComponent,
resolve: { userData: IdentityResolverService },
children: [
{
path: 'home',
component: HomeComponent,
data: { title: 'Home' },
canActivate: [AuthGuardService]
},
{
path: 'history',
component: HistoryComponent,
data: { title: 'History' },
canActivate: [AuthGuardService]
},
{
path: '404',
component: NotFoundErrorComponent,
data: { title: 'Error 404' },
canActivate: [AuthGuardService]
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
canActivate: [AuthGuardService]
},
{
path: '**',
redirectTo: '/404',
pathMatch: 'full',
data: { title: 'Error 404' },
canActivate: [AuthGuardService]
}
]
};
]
好的,我将尝试解释这一切是如何工作的。 您的问题是组件中的getCurrentUser在 localStorage 尝试获取数据后执行。
如果您的AppComponent是您的应用程序广告的根组件,则顶部导航组件在应用程序组件 html 中声明,那么您需要确保在 AppComponent 启动之前数据就在那里。
所以,会发生什么(可能的时间线,因为 javascript 的异步性质意味着有时某些步骤将以不同的顺序执行):
最好的解决方案是使用警卫。 如果您需要使用 ADUser 作为安全功能,这对您的情况更有效。 如果防护失败,那么您将不会转换到 AppComponent。
声明一个Guard ,如果数据在那里,然后继续到应用程序组件,Guard 将确保您在本地存储(或 session 存储)中有 ADUser 数据。
解析器(另一种可能的解决方案)将始终在 AppComponent 加载之前运行并且不会阻塞,从而确保在应用程序响应时您拥有数据。
更多关于守卫和解析器的信息在这里
看看下面的守卫:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private adUserService: ADUserService,
private router: Router
) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
// We will return a true if the user is logged in
// or false otherwise
return this.adUserService.login().pipe(
map((x) => {
// Since my service returned succesfully I will set the
// locale storage with the appropriate data
localStorage.setItem('user', JSON.stringify(x));
// I will also return true to let the router module
// know that it can proceed
return true;
}),
catchError(() => {
// If there was an error, I will return false, so the
// router module will not allow the transition
// if I want to, I can add the router module to transition
// to a login page
return of(false)
})
);
}
}
您可以在此处查看完整的解决方案: stackblitz 示例
要查看实际的语言环境存储,请尝试https://so-angular-route-guards-locale-storage.stackblitz.io/user url。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.