Asp.net core IHttpContextAccessor在AspNetCore 5 API控制器中返回空用户名声明

Asp.net core IHttpContextAccessor在AspNetCore 5 API控制器中返回空用户名声明,asp.net-core,asp.net-web-api,jwt,asp.net-identity,asp.net-authorization,Asp.net Core,Asp.net Web Api,Jwt,Asp.net Identity,Asp.net Authorization,在我的AspNetCore 5 web应用程序中,我有一些Api控制器,其中包含一些方法,未经身份验证的用户可以使用这些方法,其中一些方法仅适用于授权用户 假设有一个ReviewController,所有用户都可以添加该控制器,但如果用户经过身份验证,则应填写用户名字段 让我们假设在测试控制器中: [Route("api/[controller]/[action]/")] [ApiController] public class TestController { pr

在我的AspNetCore 5 web应用程序中,我有一些Api控制器,其中包含一些方法,未经身份验证的用户可以使用这些方法,其中一些方法仅适用于授权用户

假设有一个ReviewController,所有用户都可以添加该控制器,但如果用户经过身份验证,则应填写用户名字段

让我们假设在测试控制器中:

[Route("api/[controller]/[action]/")]
[ApiController]
public class TestController
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public TestController(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    [HttpGet]
    public string TestA()
    {
        return _httpContextAccessor.HttpContext.User.Identity.Name;
    }

    [HttpGet]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public string TestB()
    {
        return _httpContextAccessor.HttpContext.User.Identity.Name;
    }
}
两种方法之间的唯一区别是
Authorize
属性

我使用下面的设置在应用程序中设置JwtBearer
身份验证

配置服务:

    public override void ConfigureServices(IServiceCollection services)
    {
        var jwtConfig = new JwtConfig
        {
            Secret = "some secrets!",
            Audience = "http://localhost:5000",
            Expires = 600,
            Issuer = "http://localhost:5000"
        };

        services.AddAuthorization();

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(jwt =>
        {
            var key = Encoding.ASCII.GetBytes(jwtConfig.Secret);
            jwt.SaveToken = true;
            jwt.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true, 
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidateAudience = true,
                RequireExpirationTime = true,
                ValidateLifetime = true,
                SaveSigninToken = true,
                ValidAudience = jwtConfig.Audience,
                ValidIssuer = jwtConfig.Issuer
            };
        });

        services.AddHttpContextAccessor();

        services.AddMvcCore()
            .AddDataAnnotations()
            .AddApiExplorer()
            .AddFormatterMappings()
            .AddCors();
    }
        public void Configure(IApplicationBuilder app)
        {          
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
和配置:

    public override void ConfigureServices(IServiceCollection services)
    {
        var jwtConfig = new JwtConfig
        {
            Secret = "some secrets!",
            Audience = "http://localhost:5000",
            Expires = 600,
            Issuer = "http://localhost:5000"
        };

        services.AddAuthorization();

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(jwt =>
        {
            var key = Encoding.ASCII.GetBytes(jwtConfig.Secret);
            jwt.SaveToken = true;
            jwt.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true, 
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidateAudience = true,
                RequireExpirationTime = true,
                ValidateLifetime = true,
                SaveSigninToken = true,
                ValidAudience = jwtConfig.Audience,
                ValidIssuer = jwtConfig.Issuer
            };
        });

        services.AddHttpContextAccessor();

        services.AddMvcCore()
            .AddDataAnnotations()
            .AddApiExplorer()
            .AddFormatterMappings()
            .AddCors();
    }
        public void Configure(IApplicationBuilder app)
        {          
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
当我调用
TestB
时,它返回登录的用户名。但是,当我调用
TestA
时,它返回null


为什么未加载
IHttpContextAccessor
的用户声明,以及如何在任何情况下访问
IHttpContextAccessor
的用户名和用户声明?假设我在控制器以外的其他层中使用它。

在将
[Authorize(authorizationschemes=JwtBearerDefaults.authorizationscheme)]
更改为
[Authorize]
之后,您是否可以尝试调用
TestB
当我调用
TestB
时,您的话有冲突,如果您调用
TestB
并返回
401
,您怎么知道它返回登录的用户名(如您问题中所述)?实际上,我认为身份验证在这两种情况下都失败了(调用
TestA
TestB
)。但是
TestB
具有
authorized属性
,访问将短路并返回
401
。现在问题可能更难了,您需要检查您的请求是否包含有效的凭据信息,可能需要调试到源代码中,这实际上取决于您的实际代码。@King Michal问我是否尝试将
[Authorize(authorization(authorizationschemes=jwtbearderdefaults.authorizationscheme)]
更改为
[Authorize]
是否在张贴的代码中,我回答了这个问题。这意味着发布的代码中的
TestB
返回登录的用户名。不确定更改后会有什么不同,您的默认身份验证方案是
JwtBearerDefaults.AuthenticationScheme
,因此仅使用
[Authorize]
应该与
[Authorize(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme]相同
-我现在感到困惑。只有在不使用身份验证中间件的情况下(通过
UseAuthentication
),它们才不同。