Используя. 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 (с локальными учетными записями пользователей), с небольшим количеством проб и ошибок и расследований.
Текущее состояние моего приложения:
- Пользователь входит в приложение Razor Pages.
- Вход выполнен успешно, и электронная почта отображается на панели навигации.
- Когда мы переходим к SPA, мое приложение Angular пытается войти в систему без вывода сообщений и успешно:
localhost: 5001 / Панель инструментов (Angular домашний маршрут SPA)
![enter image description here](https://i.stack.imgur.com/8nvmS.png)
Если мы перейдем к части приложения Razor Pages, у которой нет маршрута
/Identity
(который используется только для страниц, которые имеют идентификатор), файлы cookie больше не содержат нужной информации, и у меня нет сессия в этих маршрутах. Это означает, что, например, если я использую
SignInManager.IsSignedIn(User)
только для отображения опции навигации на странице администрирования, защищенной
options.Conventions.AuthorizePage($"/Administration")
, если я нахожусь в URL-адресе с маршрутом идентификации, вкладка навигации будет будет отображаться, в противном случае он не будет отображаться:
localhost: 5001 / личность / учетная запись / логин
![enter image description here](https://i.stack.imgur.com/LPXQJ.png)
localhost: 5001 (домашний маршрут приложения Razor Pages)
![enter image description here](https://i.stack.imgur.com/nEKPc.png)
Однако, несмотря на то, что отображается вкладка «Администрирование», когда я нахожусь по URL-адресу с маршрутом
/Identity
, при нажатии на него я получу 401 несанкционированную ошибку, поскольку перед страницей администрирования не предшествует
/Identity
маршрут:
localhost: 5001 / Администрация
![enter image description here](https://i.stack.imgur.com/atDby.png)
Мне удалось проследить проблему до 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?