Aspnetcore Bearer auth:在中间件中使用用户



我在应用程序中使用了cookie和持有者身份验证。但我有奇怪的行为,我无法解释。

确实有自定义中间件,我在其中将一些必需的数据添加到上下文中。 一切都很好,但在中间件中,如果它的持有者是空的,但当它的cookie时它可以。

   services
                .AddAuthorization(options =>
                {
                    options.DefaultPolicy = new AuthorizationPolicyBuilder()
                        .AddAuthenticationSchemes(OAuthValidationDefaults.AuthenticationScheme,
                            CookieAuthenticationDefaults.AuthenticationScheme,
                            "Identity.Application")
                        .RequireAuthenticatedUser()
                        .Build();
                });
            //CookieAuthenticationDefaults.AuthenticationScheme
            services.AddAuthentication()
                .AddExternalAuthProviders(Configuration)
                .AddFlymarkOpenIdConnectServer()
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
                {
                    options.LoginPath = "/Identity/Account/LogIn";
                    options.SlidingExpiration = true;
                    options.Events.OnRedirectToLogin = OnRedirectToLogin;
                })
                .AddOAuthValidation(OAuthValidationDefaults.AuthenticationScheme,
                    o=>o.Events.OnCreateTicket = OnCreateTicket);
            services.ConfigureApplicationCookie(config =>
            {
                config.Events = new CookieAuthenticationEvents
                {
                    OnRedirectToLogin = OnRedirectToLogin
                };
            });

临时我在创建票证上使用,可以解决我的问题

   private async Task OnCreateTicket(CreateTicketContext arg)
        {
            if (arg.HttpContext.Items[FlymarkWeb.CurrentUserKey] == null && arg.Identity.IsAuthenticated)
            {
                var db= (FlymarkContext) arg.HttpContext.RequestServices.GetService(typeof(FlymarkContext));
                arg.HttpContext.Items[FlymarkWeb.CurrentUserKey] =
                    await db.Users.FirstOrDefaultAsync(u => u.Id == arg.Identity.GetUserId());
            }
        }

和中间件

  public async Task Invoke(HttpContext httpContext, FlymarkContext context, DomainService _sourceDomainService)
        {
            if (httpContext.Items[FlymarkWeb.CurrentUserKey] == null)
            {
                httpContext.Items[FlymarkWeb.CurrentUserKey] = httpContext.User.Identity.IsAuthenticated
                    ? await context.Users.FirstOrDefaultAsync(u => u.Id == httpContext.User.GetUserId())
                    : null;
            }
....
}

所以我的问题是为什么饼干和oauth不同?为什么如果它的cookie我可以在中间件中访问用户,如果它的oauth我不能?

这是因为当您调用services.AddIdentity()时 ASP.NET 核心标识将自身注册为默认身份验证方案处理程序。

当收到请求时,app.UseAuthentication()后面的中间件会自动调用 Identity 注册的 cookie 身份验证处理程序,并用从身份验证 cookie 中提取的结果ClaimsPrincipal填充HttpContext.User

对于持有者令牌,不会发生这种情况,因为 OAuth 验证处理程序不会将自身注册为默认身份验证处理程序(这是您必须在 2.0 中手动和显式执行的操作)。

要将其配置为默认处理程序,您可以这样做:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = OAuthValidationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OAuthValidationDefaults.AuthenticationScheme;
});

或者,您可以自己直接执行身份验证操作,而不是依赖 HttpContext.User 。例如:

public async Task Invoke(HttpContext httpContext, FlymarkContext context, DomainService _sourceDomainService)
{
    if (httpContext.Items[FlymarkWeb.CurrentUserKey] == null)
    {
        var principal = (await httpContext.AuthenticateAsync(OAuthValidationDefaults.AuthenticationScheme))?.Principal;
        httpContext.Items[FlymarkWeb.CurrentUserKey] = principal?.Identity != null && principal.Identity.IsAuthenticated
            ? await context.Users.FirstOrDefaultAsync(u => u.Id == principal.GetUserId())
            : null;
    }
}

最新更新