为什么 authorizeview roles="admin" 让我的应用程序崩溃?
Why does authorizeview roles="admin" crash my app?
这里是我的应用程序的简要说明:
VS2019 Blazor 应用程序,个人用户身份验证,netcore 托管。
目标是什么:基于角色的授权,为非授权用户提供隐藏链接。
在阅读了基于角色的授权之后,我最终按如下方式更改了我的服务:
我为我的数据库设置了一个管理员用户和 2 个角色,如下所示:
一切都很好。当我尝试使用 AuthorizeView Roles="admin" 隐藏 'NavMenu.razor' 页面中的非管理员链接时,我的麻烦就开始了:
更改后我的应用程序关闭并抛出以下异常:
真不知道去哪里看。 'AuthorizeView' 有效,但 'AuthorizeView Roles="admin"' 使系统陷入循环。
这可能与声明处理角色的方式有关,但我需要有经验的人帮助我解决这个问题或提出其他实现目标的方法。
谢谢!
PS:抱歉所有图片,我在格式化错误日志和 html 时遇到问题,所以我只粘贴了图片。
在我看来,问题可能出在 IdentityServer 上...
试试下面的代码,看看能不能解决问题。在客户端的 Main 方法中放置以下设置:
builder.Services.AddApiAuthorization()
.AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();
新建一个class: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;
}
}
It may have something to do with the way claims deal with roles
正是...
, but I need someone experienced to help me sort this out or suggest another way to achieve the goal.
考虑使用 policy-based (claims-based) 授权,即使您成功解决了这个问题。事实上,roles-based授权在内部实现为claims-based
这里是我的应用程序的简要说明: VS2019 Blazor 应用程序,个人用户身份验证,netcore 托管。
目标是什么:基于角色的授权,为非授权用户提供隐藏链接。
在阅读了基于角色的授权之后,我最终按如下方式更改了我的服务:
我为我的数据库设置了一个管理员用户和 2 个角色,如下所示:
一切都很好。当我尝试使用 AuthorizeView Roles="admin" 隐藏 'NavMenu.razor' 页面中的非管理员链接时,我的麻烦就开始了:
更改后我的应用程序关闭并抛出以下异常:
真不知道去哪里看。 'AuthorizeView' 有效,但 'AuthorizeView Roles="admin"' 使系统陷入循环。
这可能与声明处理角色的方式有关,但我需要有经验的人帮助我解决这个问题或提出其他实现目标的方法。
谢谢!
PS:抱歉所有图片,我在格式化错误日志和 html 时遇到问题,所以我只粘贴了图片。
在我看来,问题可能出在 IdentityServer 上...
试试下面的代码,看看能不能解决问题。在客户端的 Main 方法中放置以下设置:
builder.Services.AddApiAuthorization()
.AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();
新建一个class: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;
}
}
It may have something to do with the way claims deal with roles
正是...
, but I need someone experienced to help me sort this out or suggest another way to achieve the goal.
考虑使用 policy-based (claims-based) 授权,即使您成功解决了这个问题。事实上,roles-based授权在内部实现为claims-based