Аутентификация для. NET Приложение Core Razor Pages не работает для представлений без маршрута "/ Identity" при использовании .AddIdentityServerJwt () - PullRequest
0 голосов
/ 26 апреля 2020

Используя. NET Core 3.1 Framework, я пытаюсь настроить веб-платформу со следующей настройкой:

  • Приложение Razor Pages, которое выступает в качестве целевой страницы для платформы с функциями / страницами, такими как реклама платформы, согласие Cook ie, политика конфиденциальности, контакты и страницы, которые идут с Identity (например, логин, регистрация, управление учетной записью).
  • Аутентификация для страниц Razor Приложение выполняется стандартным способом идентификации.
  • Angular SPA, который доступен только после входа пользователя в систему.
  • OID C конфигурация с Identity Server для добавления аутентификация и авторизация в Angular SPA.

Все эти три компонента (Razor Pages + Angular + Identity Server) объединены в один. NET Базовый веб-проект. Я также создал Identity, чтобы я мог настроить внешний вид и поведение страниц.

Мне удалось почти настроить приложение так, как я хочу, по сути, смешивая код шаблонов запуска опция Razor Pages (с локальными учетными записями пользователей) и шаблон Angular (с локальными учетными записями пользователей), с небольшим количеством проб и ошибок и расследований.

Текущее состояние моего приложения:

  1. Пользователь входит в приложение Razor Pages.
  2. Вход выполнен успешно, и электронная почта отображается на панели навигации.
  3. Когда мы переходим к SPA, мое приложение Angular пытается войти в систему без вывода сообщений и успешно:

localhost: 5001 / Панель инструментов (Angular домашний маршрут SPA)

enter image description here

Если мы перейдем к части приложения Razor Pages, у которой нет маршрута /Identity (который используется только для страниц, которые имеют идентификатор), файлы cookie больше не содержат нужной информации, и у меня нет сессия в этих маршрутах. Это означает, что, например, если я использую SignInManager.IsSignedIn(User) только для отображения опции навигации на странице администрирования, защищенной options.Conventions.AuthorizePage($"/Administration"), если я нахожусь в URL-адресе с маршрутом идентификации, вкладка навигации будет будет отображаться, в противном случае он не будет отображаться:

localhost: 5001 / личность / учетная запись / логин

enter image description here

localhost: 5001 (домашний маршрут приложения Razor Pages)

enter image description here

Однако, несмотря на то, что отображается вкладка «Администрирование», когда я нахожусь по URL-адресу с маршрутом /Identity, при нажатии на него я получу 401 несанкционированную ошибку, поскольку перед страницей администрирования не предшествует /Identity маршрут:

localhost: 5001 / Администрация

enter image description here

Мне удалось проследить проблему до AddIdentityServerJwt(). Без этого логин для приложения Razor Pages работает так, как задумано, но я, очевидно, не могу впоследствии использовать аутентификацию и авторизацию с приложением Angular.

Я пошел, чтобы проверить исходный код для этого метода, и получается, что он создает новый IdentityServerJwtPolicySchemeForwardSelector, который перенаправляет схему политики JWT в DefaultIdentityUIPathPrefix, которая, как вы могли догадаться, содержит только значение "/Identity".

Я настроил свой класс запуска следующим образом:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    services.Configure<CookiePolicyOptions>(options =>
    {            
        options.CheckConsentNeeded = context => true;            
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
    services
        .AddDbContext<ApplicationDbContext>(optionsBuilder =>
        {
            DatabaseProviderFactory
                    .CreateDatabaseProvider(configuration, optionsBuilder);
        });
    services
        .AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services
        .AddIdentityServer()
        .AddApiAuthorization<IdentityUser, ApplicationDbContext>();
    services
        .AddAuthentication()
        .AddIdentityServerJwt();
    services
        .AddControllersWithViews();
    services
            .AddRazorPages()
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizePage($"/Administration");
            });       
    services
        .AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

    services.AddTransient<IEmailSender, EmailSenderService>();
    services.Configure<AuthMessageSenderOptions>(configuration);

    services.AddTransient<IProfileService, ProfileService>();
}

public void Configure(IApplicationBuilder applicationBuilder, IWebHostEnvironment webHostEnvironment)
{
    SeedData.SeedDatabase(applicationBuilder, configuration);

    if (webHostEnvironment.IsDevelopment())
    {
        applicationBuilder.UseDeveloperExceptionPage();
        applicationBuilder.UseDatabaseErrorPage();
    }
    else
    {
        applicationBuilder.UseExceptionHandler("/Error");           
        applicationBuilder.UseHsts();
    }

    applicationBuilder.UseHttpsRedirection();
    applicationBuilder.UseStaticFiles();
    applicationBuilder.UseCookiePolicy();

    if (!webHostEnvironment.IsDevelopment())
    {
        applicationBuilder.UseSpaStaticFiles();
    }

    applicationBuilder.UseRouting();

    applicationBuilder.UseAuthentication();
    applicationBuilder.UseIdentityServer();
    applicationBuilder.UseAuthorization();
    applicationBuilder.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
    });

    applicationBuilder.UseSpa(spa =>
    {              
        spa.Options.SourcePath = "ClientApp";

        if (webHostEnvironment.IsDevelopment())
        {
            if (bool.Parse(configuration["DevelopmentConfigurations:UseProxyToSpaDevelopmentServer"]))
            {
                spa.UseProxyToSpaDevelopmentServer(configuration["DevelopmentConfigurations:ProxyToSpaDevelopmentServerAddress"]);
            }
            else
            {
                spa.UseAngularCliServer(npmScript: configuration["DevelopmentConfigurations:AngularCliServerNpmScript"]);
            }
        }
    });
}

Как настроить приложение так, чтобы сеанс был доступен по всему моему приложению, а не только по URL-адресам, имеющим маршрут «/ Identity», сохраняя при этом аутентификацию и авторизацию для приложения Razor Pages и приложения Angular?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...