首页 > 解决方案 > 为什么 authorizeview roles="admin" 使我的应用程序崩溃?

问题描述

这是我的应用程序的简要说明:VS2019 Blazor 应用程序,个人用户身份验证,netcore 托管。

目标是:为非授权用户使用隐藏链接的基于角色的授权。

在阅读了基于角色的授权后,我最终改变了我的服务,如下所示: 在此处输入图像描述

我用管理员用户和 2 个角色播种了我的数据库,如下所示: 在此处输入图像描述

一切都很好。当我尝试使用 AuthorizeView Roles="admin" 在“NavMenu.razor”页面中隐藏非管理员链接时,我的麻烦就开始了: 在此处输入图像描述

更改后,我的应用程序将关闭并抛出以下异常: 在此处输入图像描述

我真的不知道在哪里看。'AuthorizeView' 有效,但 'AuthorizeView Roles="admin"' 将系统抛出一个循环。

这可能与索赔处理角色的方式有关,但我需要有经验的人来帮助我解决这个问题或提出另一种实现目标的方法。

谢谢!

PS:对不起所有的图片,我在格式化错误日志和 html 时遇到问题,所以我只是粘贴了图片。

标签: asp.net-identityblazorblazor-server-sideblazor-client-side

解决方案


在我看来,问题可能出在 IdentityServer ...

试试下面的代码,看看能不能解决问题。在客户端的 Main 方法中放置以下设置:

 builder.Services.AddApiAuthorization()
                .AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();

创建一个新类:RolesClaimsPrincipalFactory.cs

    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;


 public class RolesClaimsPrincipalFactory : AccountClaimsPrincipalFactory<RemoteUserAccount>
    {
        public RolesClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor) : base(accessor)
        {
        }
        
        public override async ValueTask<ClaimsPrincipal> CreateUserAsync(RemoteUserAccount account, RemoteAuthenticationUserOptions options)
        {
            var user = await base.CreateUserAsync(account, options);
            if (user.Identity.IsAuthenticated)
            {
                var identity = (ClaimsIdentity)user.Identity;
                var roleClaims = identity.FindAll(identity.RoleClaimType);
                if (roleClaims != null && roleClaims.Any())
                {
                    foreach (var existingClaim in roleClaims)
                    {
                        identity.RemoveClaim(existingClaim);
                    }

                    var rolesElem = account.AdditionalProperties[identity.RoleClaimType];
                    if (rolesElem is JsonElement roles)
                    {
                        if (roles.ValueKind == JsonValueKind.Array)
                        {
                            foreach (var role in roles.EnumerateArray())
                            {
                                identity.AddClaim(new Claim(options.RoleClaim, role.GetString()));
                            }
                        }
                        else
                        {
                            identity.AddClaim(new Claim(options.RoleClaim, roles.GetString()));
                        }
                    }
                }
            }

            return user;
        }
    }

这可能与声明处理角色的方式有关

确切地...

,但我需要有经验的人来帮助我解决这个问题或提出另一种实现目标的方法。

即使您成功解决了此问题,也请考虑使用基于策略(基于声明)的授权。事实上,基于角色的授权在内部实现为基于声明的


推荐阅读