【问题标题】:Authorise normal Razor Pages in a Blazor WebAssemby App?在 Blazor WebAssembly 应用程序中授权普通 Razor 页面?
【发布时间】:2020-10-21 19:01:03
【问题描述】:

我正在使用 Blazor Wasm 编写 SPA。我使用了标准模板并包含了托管在服务器中的用户帐户,该服务器也创建了一个服务器应用程序。到目前为止这一切都很好。 我要补充一点,我使用的是 .Net5 RC2,但我认为这不是我的问题。

我想在服务器和客户端应用程序中都有一些“正常”的剃须刀页面。用户帐户身份服务器创建了文件夹结构 /Areas/Identity/Pages/.... 我添加了 /Areas/Management/Pages/Admin/Test.cshtml 和 Test.cshtml.cs 这些都是非常简单的测试文件...

编辑 - 我已编辑此内容以反映@enet 提出的问题。

剃须刀文件:

        @page
        @model ProjName.Server.Areas.Management.Pages.Admin.TestModel

        <h1>Test Page</h1>

    @if (User.Identity.IsAuthenticated)
    {
        @if (User.IsInRole("Administrator"))
        {
            <h2>User is Admin</h2>
        }
        else
        {
            <h2>User is not an admin</h2>
        }
    }
    else
    {
        <h2>User is Not Authenticated</h2>
    }

        @{
        }

.CS 文件:

        namespace ProjName.Server.Areas.Management.Pages.Admin
        {
            [Authorize]    <<<--- See case B.
            public class TestModel : PageModel
            {
                public void OnGet()
                {
                }
            }
        }

我想看到页面显示用户是管理员,或者用户不是管理员。 在案例 A 中:如果 [Authorize] 被删除,页面将加载,但始终显示用户未授权。所以页面正在呈现,简单的测试产生“其他”情况.. 情况 B :页面根本不会呈现。 (此页面不工作!- 来自浏览器的消息)。所以,根据我的研究,在这个: Razor Pages Authorization Conventions

我从这里更改了我的 startup.cs:

           services.AddRazorPages();

到这里:

            services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeAreaFolder("Management", "/Admin");

        });

***我已经把上面的东西拿出来并重置为原来的样子***

当我这样做时,会出现与案例 B 相同的结果,无论 .cs 文件中是否有 [Authorize]。当您阅读文档时,我猜这是有道理的。

所以我想我需要回传某种形式的授权令牌,或者?

身份页面不需要任何授权,因此这不是问题。 我的配置服务如下所示:

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<RGDbContext>(options =>
                    options.UseSqlServer(
                        Configuration.GetConnectionString("DefaultConnection")));

                services.AddDatabaseDeveloperPageExceptionFilter();

                services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
                    .AddRoles<IdentityRole>()
                    .AddEntityFrameworkStores<RGDbContext>();

                // This was put in to try to sort this https://github.com/dotnet/AspNetCore.Docs/issues/17517
                //services.Configure<IdentityOptions>(options =>
                //    options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);

                services.AddIdentityServer()
                    .AddApiAuthorization<ApplicationUser, RGDbContext>(options => {
                        options.IdentityResources["openid"].UserClaims.Add("name");
                        options.ApiResources.Single().UserClaims.Add("name");
                        options.IdentityResources["openid"].UserClaims.Add("role");
                        options.ApiResources.Single().UserClaims.Add("role");
                    });

                services.AddAuthentication()
                    .AddIdentityServerJwt();



                services.AddControllersWithViews();
                //services.AddRazorPages();
                services.AddRazorPages(options =>
                {
                    options.Conventions.AuthorizeAreaFolder("Management", "/Admin");

                });
                

                .... more of my own stuff...

*** 到服务器页面的导航从 NavMenu 中的一个按钮触发“onclick”事件到此:

    private void ServerPageTest()
    {
        Navigation.NavigateTo("/Management/Admin/Test", true);
    }

我感觉我的创业公司缺少一些选择,任何想法..

【问题讨论】:

    标签: c# razor authorization blazor


    【解决方案1】:

    我有答案,我想……

    更改我们拥有的 Startup.cs 文件:

            services.AddAuthentication();
    

    我改成:

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
                options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
            })
    

    这允许服务器提供带有身份验证的剃须刀页面。

    它还有另一个副作用,即改变了服务器对声明的感知方式,并导致任何 API 控制器能够以更传统的控制器方式工作。我会解释的。我还有一个带有 api 端点 'AddUpdateUser' 的 'ApplicationUserController',它可以按照它在锡上所说的那样做。

    我有这个代码来检查登录的用户:

           public async Task<ActionResult<ApplicationUserDTO>> AddUpdateUser(ApplicationUserDTO sentUser)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            // Get the logged in user.
            // This line should work but doesnt and I dont know why.
            ApplicationUser loggedinUserX = await _userManager.GetUserAsync(User).ConfigureAwait(false);
    

    但它总是返回 null。所以我不得不求助于使用以下代码从声明中查找用户 ID:

            string loggedinUserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
            ApplicationUser loggedinUser = _context.Users.Find(loggedinUserId);
    

    我也不得不搜索如何做到这一点。当然是在这个很棒的网站上找到的。

    但是将这两行添加到启动中,破坏了这段代码并使原始代码工作。我想我现在明白为什么了,人们说“阅读文档”很好,但有时它太让人不知所措了。

    无论如何,我希望这对某些人有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-02-05
      • 2021-02-08
      • 2020-02-18
      • 2020-06-20
      • 2020-03-12
      • 2020-08-27
      • 2021-07-31
      • 2021-11-05
      • 2013-02-24
      相关资源
      最近更新 更多