gpt4 book ai didi

asp.net-core - 使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有 "/Identity"路由的 View

转载 作者:行者123 更新时间:2023-12-05 09:10:28 29 4
gpt4 key购买 nike

使用 .NET Core 3.1 框架,我正在尝试使用以下设置配置网络平台:

  • 一个 Razor Pages 应用程序,作为平台的登录页面,具有平台广告、cookie 同意、隐私政策、联系人和带有身份的页面(例如,登录、注册、管理)等功能/页面帐户)。
  • Razor Pages 应用程序的身份验证以标准身份方式执行。
  • 一个 Angular SPA,只有在用户登录后才能访问。
  • 使用 Identity Server 配置 OIDC,以便为 Angular SPA 添加身份验证和授权。

所有这三个组件(Razor Pages + Angular + Identity Server)都捆绑到一个 .NET Core Web 项目中。我还搭建了 Identity 脚手架,以便能够自定义页面的外观和行为。

通过基本上混合 Razor Pages 选项的启动模板代码(用户帐户存储在本地)和 Angular 模板选项(用户帐户存储在本地),我几乎能够按照我想要的方式配置应用程序并经过一些反复试验和调查。

我的申请的当前状态是:

  1. 用户登录 Razor Pages 应用程序。
  2. 登录成功,邮箱显示在导航栏上。
  3. 当我们导航到 SPA 时,我的 Angular 应用程序尝试静默登录并成功:

localhost:5001/Dashboard(Angular SPA 主路由)

enter image description here

  1. 如果我们导航到没有 /Identity 路由的 Razor Pages 应用程序部分(仅用于带有 Identity 的页面),cookie 似乎不再包含正确的信息,我在这些路线上没有 session 。这意味着,例如,如果我使用 SignInManager.IsSignedIn(User) 只显示一个导航选项到受 options.Conventions.AuthorizePage($ "/Administration"),如果我在一个有Identity路由的URL中,就会显示导航标签,否则不显示:

localhost:5001/Identity/Account/Login

enter image description here

localhost:5001(Razor Pages 应用程序主路由)

enter image description here

  1. 但是,即使当我在具有 /Identity 路由的 URL 上时显示管理导航选项卡,如果我单击它,我将收到 401 未经授权的错误,因为管理页面前面没有 /Identity 路由:

localhost:5001/Administration

enter image description here

我已设法将问题追溯到 AddIdentityServerJwt()。如果没有这个,Razor Pages 应用程序的登录将按预期工作,但我显然无法在之后对 Angular 应用程序使用身份验证和授权。

我去查了source code对于该方法,事实证明它创建了一个新的 IdentityServerJwtPolicySchemeForwardSelector 将 JWT 策略方案转发给 DefaultIdentityUIPathPrefix,您可能已经猜到了,它仅包含值 “/身份”

我已经按照以下方式配置了我的 Startup 类:

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

我如何配置我的应用程序,以便 session 在我的整个应用程序中可用,而不仅仅是在具有“/Identity”路由的 URL 上可用,同时维护 Razor Pages 应用程序和 Angular 应用程序的身份验证和授权?

最佳答案

我遇到了同样的问题并通过添加我自己的 PolicyScheme 来解决它,它根据请求路径决定应该使用哪种类型的身份验证。我所有的 Razor 页面都有一个以“/Identity”或“/Server”开头的路径,所有其他请求都应该使用 JWT。

我使用以下代码在 ConfigureServices 中进行设置:

// Add authentication using JWT and add a policy scheme to decide which type of authentication should be used
services.AddAuthentication()
.AddIdentityServerJwt()
.AddPolicyScheme("ApplicationDefinedAuthentication", null, options =>
{
options.ForwardDefaultSelector = (context) =>
{
if (context.Request.Path.StartsWithSegments(new PathString("/Identity"), StringComparison.OrdinalIgnoreCase) ||
context.Request.Path.StartsWithSegments(new PathString("/Server"), StringComparison.OrdinalIgnoreCase))
return IdentityConstants.ApplicationScheme;
else
return IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
};
});

// Use own policy scheme instead of default policy scheme that was set in method AddIdentityServerJwt
services.Configure<AuthenticationOptions>(options => options.DefaultScheme = "ApplicationDefinedAuthentication");

关于asp.net-core - 使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有 "/Identity"路由的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61435229/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com