本文介绍了在Blazor WebAssemby应用程序中授权普通Razor页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing an SPA using Blazor Wasm. I have used the standard template and included user accounts hosted in the server which has created a server app as well. This is all fine so far.I would add that I am using .Net5 RC2 but I don't think that is my issue here.

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

I want to have some 'normal' razor pages in the server as well as those in the client app. The user accounts Identity server created the folder structure /Areas/Identity/Pages/....I have added /Areas/Management/Pages/Admin/Test.cshtml and Test.cshtml.csThese are very simple test files...

编辑-我已对其进行了编辑,以反映@enet提出的问题.

EDIT - I have edited this to reflect the questions asked by @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,则该页面将完全不呈现.(此页面不起作用!-来自浏览器的消息).因此,根据我的研究,剃刀页面授权约定

I want to see the page say either User is admin, or User is not admin.In Case A : If the [Authorize] is removed, the page will load, but will always show that the user is Not authorised. So the page is being rendered and the simple test yields the 'else' case..In case B : the page will not render at all. (This page isn't working! - message from the browser). So, from my research, in this:Razor Pages Authorization Conventions

我从这里更改了startup.cs:

I changed my startup.cs from this:

           services.AddRazorPages();

对此:

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

        });

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

*** I have taken out the above and reset it to how it was ***

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

When I do that, the same result as case B ensues, with or without the [Authorize] in the .cs file. Which makes sense I guess when you read the docs.

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

So I guess I need to be passing back some form of Authorization token back, or ?

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

The Identity pages don't require any authorization so it isn't an issue there.My configure services looks like this:

            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"事件:

*** The navigation to the server page works from a button in NavMenu firing an 'onclick' event to this:

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

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

I have a feeling I am missing some options in my startup, any thoughts..

推荐答案

我认为答案是我

更改Startup.cs文件,其中包含:

Changing the Startup.cs file, where we have:

        services.AddAuthentication();

我将其更改为:

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

然后,这将允许服务器通过身份验证来提供剃须刀页面.

This then allows the server to serve up razor pages, with authentication.

它还有另一个副作用,那就是更改声明在服务器上的感知方式,并使所有API控制器能够以更传统的控制器方式工作.我会解释.我还有一个带有API端点"AddUpdateUser"的"ApplicationUserController",它的功能与罐子上说的一样.

It also had another side effect of changing how the claims are perceived back at the server, and causes any API controllers to be able to work in a more traditional controller manner. I'll explain. I also have an 'ApplicationUserController' with an api endpoint 'AddUpdateUser', which does what it says on the tin.

我有以下代码可以检查已登录的用户:

I had this code to check the logged in user:

       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.所以我不得不求助于带有以下代码的声明中的userID:

But it was always returning null. and so I had to resort to finding the userID from the claims with this code:

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

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

I'd had to search how to do this also. Found it on this great site of course.

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

But adding the two lines to the start up, the broke this code and made the original code work. I think I understand why now, and its all very well for folks to say 'read the documentation' but sometimes it's just too overwhelming.

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

Anyway, I hope this helps some people.

这篇关于在Blazor WebAssemby应用程序中授权普通Razor页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 17:11