本文介绍了Aspnetcore Bearer auth:在中间件内部使用用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在应用程序中使用Cookie和承载身份验证.但是我有一种奇怪的行为,我无法解释.

I am using cookies and bearer auth in my application. But i have strange behaviour which I can't explain.

我确实有一个自定义中间件,在其中我向Context.Items添加了一些必需的数据.这一切都很好,但是在那个中间件中,如果用户的承载是空的,那么它的cookie是可以的.

I do have custom middleware where I am adding some required data to Context.Items Its all good but in that middleware User is empty if its bearer but its ok when its cookies.

   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
                };
            });

我在CreateTicket上使用的临时解决了我的问题

Temporary I am using on CreateTicket which solve my problem

   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;
            }
....
}

所以我的问题是为什么cookie和oauth不同?为什么我的cookie可以访问中间件中的用户,为什么我的oauth无法访问?

So my question is why cookie and oauth are different? Why if its cookie I can access user in middleware and if its oauth i cant?

推荐答案

这是因为ASP.NET Core身份在调用services.AddIdentity()时将其自身注册为默认身份验证方案处理程序.

That's because ASP.NET Core Identity registers itself as the default authentication scheme handler when you call services.AddIdentity().

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

When receiving a request, the middleware behind app.UseAuthentication() will automatically call the cookie authentication handler registered by Identity and populate HttpContext.User with the resulting ClaimsPrincipal, extracted from the authentication cookie.

使用不记名令牌,这不会发生,因为OAuth验证处理程序不会将自身注册为默认的身份验证处理程序(这是您必须在2.0版中手动明确进行的操作).

With bearer tokens, this doesn't happen because the OAuth validation handler doesn't register itself as the default authentication handler (it's something you have to do manually and explicitly in 2.0).

要将其配置为默认处理程序,您可以执行以下操作:

To configure it as the default handler, you can do that:

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

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

Alternatively, you can directly perform the authentication operation yourself, instead of relying on HttpContext.User. E.g:

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;
    }
}

这篇关于Aspnetcore Bearer auth:在中间件内部使用用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 14:02