在Blazor WebAssemby应用程序中授权普通Razor页面?

时间:2020-10-21 19:01:03

标签: c# razor authorization blazor

我正在使用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中:如果删除了[授权],则将加载该页面,但始终会显示该用户未被授权。因此,正在渲染页面,并且简单的测试产生了“ else”情况。 如果是B,则该页面将完全不呈现。 (此页面不起作用!-来自浏览器的消息)。因此,根据我的研究, Razor Pages Authorization Conventions

我从这里更改了startup.cs:

           services.AddRazorPages();

对此:

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

        });

***我已取出上面的内容,并将其重置为原来的状态

执行此操作时,无论是否在.cs文件中使用[Authorize],都会产生与情况B相同的结果。当您阅读文档时,我猜这很有道理。

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

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

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

我有种感觉,我在启动时缺少一些选择。

1 个答案:

答案 0 :(得分:0)

我有答案,我想...

更改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);

我还必须搜索如何执行此操作。当然是在这个很棒的网站上找到的。

但是在启动时添加了两行,破坏了该代码并使原始代码正常工作。我想我知道现在为什么会这样,对于人们来说说“阅读文档”非常好,但是有时候它实在是太压倒性了。

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