-->

CustomRequestCultureProvider: context.User.Identit

2019-07-29 00:05发布

问题:

I'm trying to implement a CustomRequestCultureProvider in my localization pipeline, to retrieve the user culture from the database. To identify the user, I need the ClaimsPrincipal, but for some reason, even though the user is authenticated, context.User.Identity.IsAuthenticated is always false.

Here's the relevant code (truncated to highlight my issue: authentication is already working; localization code is based on the localization tutorial).

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("fr"),
                new CultureInfo("en"),
            };

            options.DefaultRequestCulture = new RequestCulture("fr");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;

            // we insert at 2, because we want to first check the query, then the cookie, then the DB, then the headers
            options.RequestCultureProviders.Insert(2, new CustomRequestCultureProvider(async context =>
            {
                // ----->> ISSUE IS HERE: this is always false!
                if (context.User.Identity.IsAuthenticated)
                    return new ProviderCultureResult("en");

                return null;
            }));
        });

        services
            .AddLocalization(options => options.ResourcesPath = "Resources")
            .AddMvc()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            ;

        return services;
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseRequestLocalization();
        app.UseStaticFiles();
        app.UseAuthentication();
        app.UseMvcWithDefaultRoute();
        return app;
    }
}

What should I do to retrieve the ClaimsPrincipal in my CustomRequestCultureProvider?

Note: changing the registration order (calling app.UseAuthentification before app.UseRequestLocalization doesn't fix the issue).

回答1:

Just in case anybody runs into this in the future I had a similar issue in ASP.NET Core 2.1 and it turned out that I was registering the authentication middleware after inserting the CustomRequestCultureProvider. To fix it I moved app.UseAuthentication() above options.RequestCultureProviders.Insert(...



回答2:

I managed to make it work by manually calling the authentication pipeline. I suspect I need to do that because the Authorize attribute is triggered later in the middleware pipeline, and thus it's too early to retrieve the ClaimsPrincipal (I might be wrong).

In any case, here's how I modified my CustomRequestCultureProvider:

// we insert at 2, because we want to first check the query, then the cookie, then the DB, then the headers
options.RequestCultureProviders.Insert(2, new CustomRequestCultureProvider(async context =>
{
    // retrieve the ClaimsPrincipal from the cookies
    // note: this is dependent on how your authentication is set up
    var authResult = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    if (!authResult.Succeeded)
        return null;

    var user = authResult.Principal;
    if (user != null)
        return new ProviderCultureResult("en");

    return null;
}));