如何修复 UserPrincipal 从 API 调用返回空字符串
How to fix UserPrincipal returning empty string from API call
我在 windows 服务器 2012 上有一个 .net-core 2.2 应用程序 运行ning,使用 angular 作为前端 SPA。在 windows 域中,我集成了 windows 身份验证 运行ning,在 IIS 服务器上,我也有站点 运行 Windows 身份验证,主要问题似乎出在 AppPool 的服务帐户 运行 上,如果我 运行 使用我的 AD 凭据的站点,该站点 return 的用户名会显示在 angular 前端正确,带有
欢迎,约翰·史密斯
当我 运行 使用我们安全团队创建的服务帐户的 AppPool 时,站点 return 的用户名是
" "
空字符串。我确认 运行s 应用程序池的服务帐户确实可以访问 Active Directory,此时我不知道还有什么可能是错误的。
- 我已经使用我的 AD 帐户 运行 AppPool 和网站 运行 没问题。 (这个有效)
- 我 运行 AppPool 与服务帐户,但该站点没有正确 return UserPrincipal。 (破)
- 我已经确认服务帐户可以通过 运行将 AD 用户和组作为服务帐户(有效)读入 Active Directory
API 控制器:
```
#region Get the logged in user
[HttpGet("api/getLoggedInUserObject")]
public async Task<ActionResult> CheckForLoggedInUser()
{
try
{
var user = await userResolverSerivce.GetUserObject();
return Ok(user);
}
catch (Exception ex)
{
Debug.Write(ex.InnerException.ToString());
throw new Exception("User is not logged in");
}
}
#endregion
```
用户主要回购
```
public class UserResolver : IUserResolver
{
private AuthorizedGroups AuthorizedGroups { get; set; }
private User _user { get; set; }
public UserResolver(IOptions<AuthorizedGroups> authorizedGroups, User user)
{
AuthorizedGroups = authorizedGroups.Value;
_user = user;
}
public Task<User> GetUserObject()
{
_user.FirstName = UserPrincipal.Current.GivenName;
_user.LastName = UserPrincipal.Current.Surname;
_user.FullName = $"{_user.FirstName} {_user.LastName}";
_user.AuthorizedRoles = GetAuthorizedRoles();
return Task.FromResult(_user);
}
```
Angular HTML:
```
<div>
<nav class="navbar-dark nav-bar-large bg-dark fixed-top">
<span class="pull-right userHighlight">Welcome, {{data.userData.fullName}}</span>
<div class="container" id="navbarNav">
<img class="image-center" src="../../assets/img/logo_sm.png" />
</div>
</nav>
</div>
```
Angular 技术专家:
```
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { UserService } from '../services/user.service';
import { User } from '../models/user';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-main-container',
templateUrl: './main-container.component.html',
styleUrls: ['./main-container.component.css'],
encapsulation: ViewEncapsulation.None
})
export class MainContainerComponent implements OnInit {
private data: any;
private user: User[];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.data = this.route.snapshot.data;
console.log(this.route.snapshot.data);
}
}
```
预期的输出应该是 return 服务帐户下的用户名,而不是空字符串,我一直在摸索为什么一个服务帐户有效而另一个无效。控制台没有错误。
您需要的是获得呼叫者的身份,并且您假设在使用 windows 身份验证时,您应该获得它。
但是.Net 核心API 不支持模拟。解决方法是使用以下代码获取用户名
以下代码可能对您有所帮助:
app.Run(async (context) =>
{
try
{
var user = (WindowsIdentity)context.User.Identity;
await context.Response
.WriteAsync($"User: {user.Name}\tState: {user.ImpersonationLevel}\n");
WindowsIdentity.RunImpersonated(user.AccessToken, () =>
{
var impersonatedUser = WindowsIdentity.GetCurrent();
var message =
$"User: {impersonatedUser.Name}\t" +
$"State: {impersonatedUser.ImpersonationLevel}";
var bytes = Encoding.UTF8.GetBytes(message);
context.Response.Body.Write(bytes, 0, bytes.Length);
});
}
catch (Exception e)
{
await context.Response.WriteAsync(e.ToString());
}
});
我在 windows 服务器 2012 上有一个 .net-core 2.2 应用程序 运行ning,使用 angular 作为前端 SPA。在 windows 域中,我集成了 windows 身份验证 运行ning,在 IIS 服务器上,我也有站点 运行 Windows 身份验证,主要问题似乎出在 AppPool 的服务帐户 运行 上,如果我 运行 使用我的 AD 凭据的站点,该站点 return 的用户名会显示在 angular 前端正确,带有
欢迎,约翰·史密斯
当我 运行 使用我们安全团队创建的服务帐户的 AppPool 时,站点 return 的用户名是
" "
空字符串。我确认 运行s 应用程序池的服务帐户确实可以访问 Active Directory,此时我不知道还有什么可能是错误的。
- 我已经使用我的 AD 帐户 运行 AppPool 和网站 运行 没问题。 (这个有效)
- 我 运行 AppPool 与服务帐户,但该站点没有正确 return UserPrincipal。 (破)
- 我已经确认服务帐户可以通过 运行将 AD 用户和组作为服务帐户(有效)读入 Active Directory
API 控制器:
```
#region Get the logged in user
[HttpGet("api/getLoggedInUserObject")]
public async Task<ActionResult> CheckForLoggedInUser()
{
try
{
var user = await userResolverSerivce.GetUserObject();
return Ok(user);
}
catch (Exception ex)
{
Debug.Write(ex.InnerException.ToString());
throw new Exception("User is not logged in");
}
}
#endregion
```
用户主要回购
```
public class UserResolver : IUserResolver
{
private AuthorizedGroups AuthorizedGroups { get; set; }
private User _user { get; set; }
public UserResolver(IOptions<AuthorizedGroups> authorizedGroups, User user)
{
AuthorizedGroups = authorizedGroups.Value;
_user = user;
}
public Task<User> GetUserObject()
{
_user.FirstName = UserPrincipal.Current.GivenName;
_user.LastName = UserPrincipal.Current.Surname;
_user.FullName = $"{_user.FirstName} {_user.LastName}";
_user.AuthorizedRoles = GetAuthorizedRoles();
return Task.FromResult(_user);
}
```
Angular HTML:
```
<div>
<nav class="navbar-dark nav-bar-large bg-dark fixed-top">
<span class="pull-right userHighlight">Welcome, {{data.userData.fullName}}</span>
<div class="container" id="navbarNav">
<img class="image-center" src="../../assets/img/logo_sm.png" />
</div>
</nav>
</div>
```
Angular 技术专家:
```
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { UserService } from '../services/user.service';
import { User } from '../models/user';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-main-container',
templateUrl: './main-container.component.html',
styleUrls: ['./main-container.component.css'],
encapsulation: ViewEncapsulation.None
})
export class MainContainerComponent implements OnInit {
private data: any;
private user: User[];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.data = this.route.snapshot.data;
console.log(this.route.snapshot.data);
}
}
```
预期的输出应该是 return 服务帐户下的用户名,而不是空字符串,我一直在摸索为什么一个服务帐户有效而另一个无效。控制台没有错误。
您需要的是获得呼叫者的身份,并且您假设在使用 windows 身份验证时,您应该获得它。
但是.Net 核心API 不支持模拟。解决方法是使用以下代码获取用户名
以下代码可能对您有所帮助:
app.Run(async (context) =>
{
try
{
var user = (WindowsIdentity)context.User.Identity;
await context.Response
.WriteAsync($"User: {user.Name}\tState: {user.ImpersonationLevel}\n");
WindowsIdentity.RunImpersonated(user.AccessToken, () =>
{
var impersonatedUser = WindowsIdentity.GetCurrent();
var message =
$"User: {impersonatedUser.Name}\t" +
$"State: {impersonatedUser.ImpersonationLevel}";
var bytes = Encoding.UTF8.GetBytes(message);
context.Response.Body.Write(bytes, 0, bytes.Length);
});
}
catch (Exception e)
{
await context.Response.WriteAsync(e.ToString());
}
});