我遵循了此处的文档,并能够让我的控制器使用[Authorize]
标头。我正在使用带有 ASP.NET 身份的 IdentityServer 作为我的用户存储。
在我的ConfigureServices
中,我有:
services.AddIdentity<KipUser, IdentityRole>()
.AddEntityFrameworkStores<KipDbContext>()
.AddDefaultTokenProviders();
在我的Configure
中,我有:
app.UseIdentityServer();
app.UseAuthorization();
在我的控制器中,我做了一些测试:
[Authorize]
public IEnumerable<MyDTO> GetData(int count = 3) {
var test = User; // The User.Identity.Name is empty for some reason
var id = User.FindFirst(ClaimTypes.NameIdentifier).Value; // Successfully gets the Guid
var test2 = _userManager.GetUserAsync(User); // result is null
var test3 = _userManager.GetUserId(User); //returns null
var test4 = _userManager.FindByIdAsync(id); // Successfully gets the User from the DB
似乎存在配置错误,因为用户管理器无法从ClaimsPrincipal User
变量获取 ASP.Net 标识。我是否过多地假设.AddEntityFrameworkStores<KipDbContext>()
会将应用程序配置为知道如何_userManager.GetUserAsync(User)
,而不是我需要使用此_userManager.FindByIdAsync(User.FindFirst(ClaimTypes.NameIdentifier).Value)
自己搜索声明?
我问这个问题的主要原因是因为我看到了很多关于 IdentityServer 2 和 3 的信息,这些信息似乎相关。我无法在我的 IdentityServer 4 项目中使用这些修复程序,所以我认为这是一个不同的问题。这是同样的问题。正如@Tore指出的那样,这是索赔的问题,但我认为这将得到app.UseIdentityServer();
这清楚地描述了问题:
UseIdentity 和 UserManager 在用户 ID 声明的存储位置上存在分歧
尽管我们正在调用app.UseIdentityServer();
但似乎有一些Microsoft输入的默认映射需要清除。
根据该问题,在app.UseIdentityServer();
之前在Startup.cs
Configure
函数中添加JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
为我解决了问题。我现在可以看到控制器中的声明没有变化,并且_userManager.GetUserAsync(User);
和_userManager.GetUserId(User);
都按预期工作。
令人惊讶的是,此函数调用未包含在IdentityServerAspNetIdentity
示例项目中。
您可以尝试将其添加到客户端。它修复了Microsoft认为的名称与身份服务器认为的名称声明之间的映射。
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
为了补充这个答案,我写了一篇博客文章,详细介绍了 关于本主题:调试 ASP.NET Core 中的 OpenID 连接声明问题