c# - HttpContext 用户声明为空

标签 c# .net identityserver4 .net-5

我之前有一个使用 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 CoreTroubleshooting JwtBearer authentication problems in ASP.NET Core

关于c# - HttpContext 用户声明为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67071166/

相关文章:

.net - 我应该将服务属性应用于接口(interface)、具体类还是两者?

c# - 从自定义 httpHandlers 评估 ASPX 页面

c# - Asp.net Core 2 使用 Identity Server 4 启用 Multi-Tenancy

asp.net-web-api - 如何使用 IdentityServer4 访问我当前的用户?

c# - 是否可以更改 WPF 中禁用按钮的背景颜色?

C# 字典映射

c# - 使用 ReSharper 在 Visual Studio 的自动格式化中换行和换行

c# - 邦兹有什么作用? Windows 移动 C#

c# - 在 dbcontext 中的请求之间存储数据

asp.net-web-api - 如何在 IdentityServer4 中运行时添加/管理用户声明