我之前有一个使用 IdentityServer 和 .Net Core 2.2 的工作项目
我最近将该项目的 .Net 版本从 Core 2.2 升级到 .Net 5。还将每个包更新到最新版本。对我的代码进行了一些调整,最终消除了所有错误。我正在 WEB API 上测试我的身份服务器功能,由于某种原因,HttpContext.User.Claims 返回空。
这是我的代码。
public Guid? CurrentUserId
{
get
{
var claimNameIdentifier = User.Claims.FirstOrDefault(a => a.Type == ClaimTypes.NameIdentifier)?.Value;
return claimNameIdentifier != null ? Guid.Parse(claimNameIdentifier) : (Guid?)null;
}
}
我在基本 Controller 上有这个,由我的端点 Controller 实现,以获取访问我的端点的 JWT 上的用户 ID。不确定这是否是由于更新造成的,因为这之前是有效的。
这是我的身份服务器的配置
public static IEnumerable<IdentityResource> IdentityResources =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
public static IEnumerable<ApiResource> ApiResources =>
new List<ApiResource>
{
new ApiResource
{
Name = "ssi.api",
DisplayName = "Standing Settlement Instructions API"
}
};
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope>
{
new ApiScope
{
Name = "ssi.api",
DisplayName = "Standing Settlement Instructions API"
}
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "ssi.front",
ClientName = "SSI Client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
// secret for authentication
ClientSecrets =
{
new Secret("my secret".Sha256())
},
// scopes that client has access to
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"ssi.api",
JwtClaimTypes.Role
},
AccessTokenLifetime = 14400,
AllowOfflineAccess = true,
}
};
这是我的配置服务的样子:
// Database
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("Server=localhost; Database = SsiDB; Integrated Security = SSPI; MultipleActiveResultSets=true;"));
#region Identity
services.AddIdentity<User, Role>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.User.RequireUniqueEmail = true;
})
.AddRoles<Role>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var identityBuilder = services.AddIdentityServer()
.AddInMemoryPersistedGrants()
.AddInMemoryClients(IdentityConfig.Clients)
.AddInMemoryApiResources(IdentityConfig.ApiResources)
.AddInMemoryApiScopes(IdentityConfig.ApiScopes)
.AddAspNetIdentity<User>();
identityBuilder.Services.AddTransient<IResourceOwnerPasswordValidator, OwnerPasswordValidator>();
identityBuilder.Services.AddTransient<IProfileService, IdentityProfileService>();
identityBuilder.AddSigningCredential(new X509Certificate2("StandingSettlementInstructionsIdentityAuth.pfx", "", X509KeyStorageFlags.MachineKeySet)); //release
#endregion
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = appSettings.ApiUrl;
options.Audience = "ssi.api";
options.RequireHttpsMetadata = false;
});
这是我的配置
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHsts();
string appDataPath = Directory.GetCurrentDirectory() + @"\AppData";
if (!Directory.Exists(appDataPath))
Directory.CreateDirectory(appDataPath);
app.UseSwaggerUI(o =>
{
o.DocumentTitle = "Standing Settlement Instructions Api Documentation";
o.RoutePrefix = "api-docs";
o.SwaggerEndpoint("/swagger/v1/swagger.json", "Version 1");
});
app.UseSwagger();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<NotificationHubService>("/NotificationHubService");
});
app.Run((context =>
{
context.Response.Redirect("api-docs");
return Task.CompletedTask;
}));
}
我尝试过的事情:
- 在ConfigureService
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
上添加了此内容并在我的基本 Controller 上使用它。结果相同 - 根据一些 Google 搜索重新安排对配置方法的调用
- 添加了对 API 资源和 API 范围的声明。结果相同
一些观察。访问 localhost/.well-known/openid-configuration 显示空的受支持声明,当我在 API 资源或 API 范围上添加声明时,它确实出现在其中,但在提取声明时仍然遇到相同的问题。还是空的。
任何帮助将不胜感激。我一直在为这件事揪心。谢谢!
最佳答案
调试声明问题的第一步是实际查看访问 token 实际包含什么?使用类似 https://jwt.io/ 的工具来做到这一点。
那么 Microsoft 和 IdentityServer 对于声明的名称应该是什么有不同的意见,因此您需要指出哪个声明是名称声明,方法是:
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters.RoleClaimType = "roles";
opt.TokenValidationParameters.NameClaimType = "name";
...
为了补充这个答案,我写了一篇博客文章,详细介绍了这个主题:Debugging JwtBearer Claim Problems in ASP.NET Core和 Troubleshooting JwtBearer authentication problems in ASP.NET Core
关于c# - HttpContext 用户声明为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67071166/