c# – 用户似乎没有在dotnetcore 2.0中的`Use`里面的pipline中进行身份验证

我正在尝试向Serilog提供ActiveUser属性.
不幸的是,我似乎无法找到检查当前用户的正确位置.

在下面的代码中,httpContext.User.Identity.IsAuthenticated始终为false?

但只有在使用承载令牌登录时才会使用

>在用户所在的范围内,承载令牌登录正常工作
对控制器方法进行了身份验证,并且用户需要属于
正确的角色,以便进行身份验证.虽然未正确设置用户名 – 但声明存在,并且IsAuthenticated设置为true.
>如果我使用cookie登录,则用户设置正确,声明设置正确,并且Serilog正常工作.无论是使用持票令牌还是cookie来调用都是如此.一旦用户使用cookie登录,它始终有效.

当验证承载令牌时,不会立即设置用户?

该项目是aspnetcore 2.0

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    ... (other configuration items)

    app.UseIdentityServer();
    app.UseAuthentication();

    app.Use(async (httpContext, next) =>
    {
        // HERE IsAuthenticated IS ALWAYS FALSE
        // HERE THE CLAIMS ARE ALWAYS EMPTY, UNLESS
        // I LOGIN USING THE COOKIE AS WELL - THEN IT WORKS
        var userName = httpContext.User.Identity.IsAuthenticated 
            ? httpContext.User.GetClaim("name")
            : "(unknown)";
        LogContext.PushProperty(
            "ActiveUser",
            !string.IsNullOrWhiteSpace(userName)
                 ? userName
                 : "(unknown)");
        await next.Invoke();
    });

    app.UseMvc(
        routes =>
        {
            routes.MapRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");
        });

在我的控制器方法中,用户设置正确,并经过身份验证.

[Authorize]
[HttpGet("user")]
public object UserDetail()
{
    // HERE THE CLAIMS ARE SET, IsAuthenticated IS ALWAYS TRUE
    // AS THE USER MUST BE AUTHENTICATED TO GET HERE
    Debug.Assert(this.User.Identity.IsAuthenticated == true)

编辑
进一步深入研究问题,看来JWTBearer令牌在我的中间件已经执行之后得到验证.中间件需要在验证令牌后执行.

TL; DR
(完整配置)

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    app.UseIdentityServer();
    app.UseAuthentication();
    app.Use(async (httpContext, next) =>
                    {
                        var userName = httpContext.User.Identity.IsAuthenticated 
                        ? httpContext.User.GetClaim("email")
                        : "(unknown)";
                        LogContext.PushProperty("ActiveUser", !string.IsNullOrWhiteSpace(userName) ? userName : "(unknown)");
                        await next.Invoke();
                    });

    app.UseMvc(
        routes =>
        {
            routes.MapRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");
        });

}

(更多配置)

   public void ConfigureServices(IServiceCollection services)
   {
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        services.AddAuthentication()
            .AddOpenIdConnect(
                o =>
                {
                    o.Authority = "https://localhost:44319";
                    o.ClientId = "api";
                    o.ClientSecret = "secret";
                    o.RequireHttpsMetadata = false;
                    o.ResponseType = "code id_token token";
                    o.GetClaimsFromUserInfoEndpoint = true;
                })
            .AddJwtBearer(
                o =>
                {
                    o.Authority = "https://localhost:44319";
                    o.Audience = "api";
                    o.RequireHttpsMetadata = false;
                    //o.SaveToken = true;
                });

        services.AddMemoryCache();
        services.AddIdentity<ApplicationUser, ApplicationRole>(
                x =>
                {
                    x.Password.RequireNonAlphanumeric = false;
                    x.Password.RequireUppercase = false;
                })
            .AddEntityFrameworkStores<FormWorkxContext>()
            .AddDefaultTokenProviders()
            .AddIdentityServer();

        // NB
        services.Configure<IdentityOptions>(
            options =>
            {
                options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
                options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
            });

        services.ConfigureApplicationCookie(
            options =>
            {
                options.LoginPath = "/login";
                options.LogoutPath = "/logout";
                options.Events.OnRedirectToLogin = this.ProcessStatusCodeResponse;
            });

        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApis())
            .AddInMemoryClients(Config.GetClients())
            .AddAspNetIdentity<ApplicationUser>();

        services.AddTransient<IEmailSender, EmailSender>();

        services.AddMvc(
                _ =>
                {
                    _.Filters.Add(
                        new AuthorizeFilter(
                            new AuthorizationPolicyBuilder(
                                    JwtBearerDefaults.AuthenticationScheme,
                                    IdentityConstants.ApplicationScheme)
                                .RequireAuthenticatedUser()
                                .Build()));
                    _.Filters.Add(new ExceptionFilter());
                    _.ModelBinderProviders.Insert(0, new PartyModelBinderProvider());
                    _.ModelBinderProviders.Insert(0, new DbGeographyModelBinder());
                    _.ModelMetadataDetailsProviders.Add(new KeyTypeModelMetadataProvider());
                })
            .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<Startup>())
            .AddJsonOptions(json => json.SerializerSettings.Converters.Add(new DbGeographyJsonConverter()));
    }

解决方法:

我使用如下的主体设置登录时复制了此问题:

var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

然后我使用SignInAsync登录.这也导致User.Identity.Name具有值,但User.Identity.IsAuthenticated未设置为true.

现在,当我将validationType参数添加到ClaimsIdentity时,如下所示:

var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "local"));

IsAuthenticated现在设置为true.

我不完全确定你的登录是如何工作的,你可以在某处提到这个authenticationType,或者你可以在创建JWT时传递它.这就是我做的方式.

更新确定只是注意到您关于名称未显示的评论,但您仍然可以尝试设置authenticationType.此外,就您的声明而言,您应该能够使用AuthenticateAsync提取原则.一旦您可以从Context.User对象访问该原则,您始终可以自定义要在主体中强制使用的身份验证方案.

更新2在您的情况下,在AddJwtBearer中,尝试包括:

o.Events.OnTokenValidated = async (context) => {
    context.Principal = new ClaimsPrincipal(new ClaimsIdentity(context.Principal.Claims, "local"));
};
上一篇:Cerilog HTTP Sink Logstash:将Serilog消息数组拆分为单个日志事件


下一篇:nn.Embedding