为啥 authorizeview roles="admin" 使我的应用程序崩溃?

Posted

技术标签:

【中文标题】为啥 authorizeview roles="admin" 使我的应用程序崩溃?【英文标题】:Why does authorizeview roles="admin" crash my app?为什么 authorizeview roles="admin" 使我的应用程序崩溃? 【发布时间】:2021-01-15 15:32:10 【问题描述】:

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

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

阅读基于角色的授权后,我最终更改了我的服务,如下所示:

我使用管理员用户和 2 个角色为我的数据库播种,如下所示:

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

更改后我的应用程序将关闭并抛出以下异常:

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

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

谢谢!

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

【问题讨论】:

【参考方案1】:

在我看来问题可能出在 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;
        
    

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

正是……

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

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

【讨论】:

感谢您提供的所有信息和帮助。我相信您对基于政策的看法是正确的。这意味着回到绘图板上,但由于 Microsoft 似乎不支持 Blazor 中经典的基于角色的系统,因此最好使用他们支持的系统。在我过渡之前,我将尝试你的代码。再次感谢! OK 测试了代码,运行良好。我仍然需要在控制器中对其进行测试,但它修复了客户端。 =) 刚刚测试了服务器端没有问题。再次感谢。 所以这会将角色数组转换为单例声明?从而处理类型问题? 知道了,谢谢

以上是关于为啥 authorizeview roles="admin" 使我的应用程序崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

行内文本显示的空检查

为啥 q/\\a/ 等于 q/\a/?

Ruby:为啥 unpack('Q') 给出的结果与手动转换不同?

为啥我们更喜欢在角度中使用 $q 而不是 $http [重复]

为啥在使用promise时使用Q,bluebird框架? [复制]

为啥 vld4q_f32 与 4x vld1q_f32 不一样?