使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有“/Identity”路由的视图

2023-12-02

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

  • 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 应用程序尝试静默登录并成功:

本地主机:5001/Dashboard(Angular SPA 主路由)

enter image description here

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

本地主机:5001/身份/帐户/登录

enter image description here

本地主机:5001(Razor Pages 应用程序主路由)

enter image description here

  1. 但是,即使当我位于具有以下内容的 URL 时,也会显示“管理”导航选项卡/Identity路线,如果我点击它,我会收到 401 未经授权的错误,因为管理页面前面没有/Identity route:

本地主机: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"]);
            }
        }
    });
}

如何配置我的应用程序,以便会话在整个应用程序中可用,而不仅仅是在具有“/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");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有“/Identity”路由的视图 的相关文章

随机推荐

  • 我可以取消引用整数指针的地址吗?

    考虑到以下给定 我试图找出填充 int 指针 k 的所有可能方法 int i 40 int p i int k 到目前为止我想出了 i 和 p 但是 是否可以用 p 或 p 来填空呢 我对 p 的理解是它取消引用整数指针的地址 对我来说这意
  • 如何在Struts 2中通过id而不是属性从JSP获取数据到Action类?

    我正在Java Struts 2框架上做 通常 我可以通过 get set 方法从我的 JSP 中获取数据Form java 动作类 下面是我的例子 In main jsp file
  • npm 安装错误:“主机密钥验证失败。”

    我想从 Bitbucket 获取该模块 我在 Windows 服务器上构建了该模块 但是当我使用时出现错误npm install npm ERR Error while executing npm ERR C Users AppData L
  • 如何在访问期间知道ANTLR解析器当前处于哪个替代规则

    如果我们查看 bash 源代码 特别是 yacc 语法 我们可以看到所有重定向都是这样定义的 redirection GREATER WORD LESS WORD NUMBER GREATER WORD NUMBER LESS WORD R
  • 如何让 date_part 查询命中索引?

    我还没有能够让这个查询命中索引而不是执行完整扫描 我有另一个查询 它对几乎相同的表使用 date part day datelocal 该表的数据稍微少一些 但是相同的结构 并且将命中我在 datelocal 列上创建的索引 这是一个没有时
  • C# - 如何使用 TaskSchedular 类列出特定用户的计划任务

    我想知道是否有人可以帮助我 我正在尝试使用 TaskScheduler 类 http www codeproject com KB cs tsnewlib aspx 列出本地计算机上特定用户 管理员 的计划任务我有以下内容 richText
  • 剪一段阿拉伯字符串

    我有一个阿拉伯语字符串 例如 现在我需要剪切这个字符串并输出它 如下所示 我尝试了这个功能 function short name str limit if limit lt 3 limit 3 if strlen str gt limit
  • 从 codecommit 获取私人仓库

    我是 golang 新手 我们正在尝试在 go 中创建一个包并在我们想要使用的所有服务中使用 我尝试在 github 中创建一个存储库并尝试执行 go get 我没有遇到任何问题 现在我想在亚马逊的codecommit中创建相同的包 我将
  • WPF Listview:列重新排序事件?

    当用户更改顺序时 我需要同步两个 ListViews 事件的列顺序 但似乎没有列重新排序事件 目前我只是做了一个AllowsColumnReorder False 但这不是一个永久的解决方案 在网上搜索时 发现很多人都有同样的问题 但没有解
  • 膨胀类 android.widget.ImageButton 时出错

    当我在 系统 应用程序 上安装程序时出现错误 当我使用 数据 应用程序 时 它运行良好 这是错误 android view InflateException Binary XML file line 19 Error inflating c
  • 检查 BIT 列时 LINQ 生成奇怪的 SQL

    我有以下 LINQtoSQL 语句 from t1 in table1 join t2 in table2 on t1 Id equals t2 OtherTableId where t2 BranchId branchId t1 IsPe
  • 在egrep中匹配As后跟相同数量的B

    假设我想匹配一个具有完全相同数量的字符 A 和 B 的模式 这样正好有 n 个 A 后跟 n 个 B 例如 可以匹配以下字符串 AB AABB AAABBB 另一方面 这些字符串无法匹配 BA AAABB AABBB ABAB 为了解决这个
  • SVN 提交未完成

    当我在 svn 中提交文件时 我经常遇到这样的情况 在传输完所有文件后 svn 将挂起 然后最终超时并出现错误svn E175012 Connection timed out 当我上传超过 20 个文件时 似乎会发生这种情况 我相信这是在所
  • C - 将字符串拆分为字符串数组

    我不完全确定如何在 C 中执行此操作 char curToken strtok string curToken ls l we will say I need a array of strings containing ls l and N
  • c++ static_assert 在“if constexpr 语句”的两个分支上均失败

    我试图在编译时确定特定类型是否属于类型标准 对 当我编译下面的代码时 两个分支 即 HERE1 和 HERE2 上的断言均失败 如果我删除 static asserts 并取消注释打印 我会得到我所期望的 这是 HERE1 的is pair
  • 使用三角形网格纹理,无需读/写图像文件

    这是上一个问题的后续 请参阅在javafx上为三角形网格中的各个三角形着色 我认为这本身就是另一个话题 有没有一种方法 使用javafx 可以让我不必实际将图像文件写入磁盘 或外部设备 来使用纹理 换句话说 我可以使用特定的纹理而不必使用图
  • 加载网页,执行其 JavaScript 并将生成的 HTML 转储到文件

    我需要加载一个网页 执行其 JavaScript 以及标签中包含的所有 js 文件 并将生成的 HTLM 转储到文件中 这需要在服务器上完成 我已经尝试过使用node js和zombie js 但它似乎太不成熟 无法在现实世界中工作 通常
  • C# 在特定情况下使用小数位格式化百分比

    在我正在构建的应用程序中 我需要按以下方式格式化百分比 00012 gt 0 01 0012 gt 0 12 012 gt 1 2 12 gt 12 1 12 gt 112 小于 1 的百分比应显示 2 位小数 任何 1 或大于 1 的值都
  • 动态加载数据到Gridview

    当我在 gridview 上工作时 我遇到了以下问题 任何帮助将不胜感激 当我将数据加载到 gridview 时 它仅加载数组的前 3 个项目 但还有 18 个项目需要加载 为什么它不加载其他 15 个项目 Log i 显示了我的 LogC
  • 使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有“/Identity”路由的视图

    使用 NET Core 3 1 框架 我尝试使用以下设置配置 Web 平台 Razor Pages 应用程序 充当平台的登陆页面 具有平台广告 cookie 同意 隐私政策 联系人以及身份附带的页面 例如登录 注册 管理帐户 等功能 页面