Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Identityserver4 Blazor级联视图策略不工作_Identityserver4_Blazor Webassembly_.net 5_Matblazor - Fatal编程技术网

Identityserver4 Blazor级联视图策略不工作

Identityserver4 Blazor级联视图策略不工作,identityserver4,blazor-webassembly,.net-5,matblazor,Identityserver4,Blazor Webassembly,.net 5,Matblazor,我正在开发一个新项目,该项目将针对用户可以访问或不能访问/查看的内容制定一些深入的策略,使用Identity Server 4 我试图使用AuthorizeView和策略来隐藏导航中的选项,但视图是层叠的,这意味着我有如下内容: <MatNavMenu> <MatNavItem Href="/home" Title="Home"><MatIcon Icon="@MatIconNames.Home">&

我正在开发一个新项目,该项目将针对用户可以访问或不能访问/查看的内容制定一些深入的策略,使用Identity Server 4

我试图使用AuthorizeView和策略来隐藏导航中的选项,但视图是层叠的,这意味着我有如下内容:

<MatNavMenu>
<MatNavItem Href="/home" Title="Home"><MatIcon Icon="@MatIconNames.Home"></MatIcon>&nbsp; Home</MatNavItem>
<MatNavItem Href="/claims" Title="Claims"><MatIcon Icon="@MatIconNames.Vpn_key"></MatIcon>&nbsp; Claims</MatNavItem>
<AuthorizeView Policy="@PolicyNames.IdentitySystemAccess">
    <Authorized>
        <AuthorizeView Policy="@PolicyNames.AccessManagement">
            <Authorized>
                <MatNavSubMenu @bind-Expanded="@_accessSubMenuState">
                    <MatNavSubMenuHeader>
                        <MatNavItem AllowSelection="false">&nbsp; Access Management</MatNavItem>
                    </MatNavSubMenuHeader>
                    <MatNavSubMenuList>
                        <AuthorizeView Policy="@PolicyNames.User">
                            <Authorized>
                                <MatNavItem Href="users" Title="users"><MatIcon Icon="@MatIconNames.People"></MatIcon>&nbsp; Users</MatNavItem>
                            </Authorized>                               
                        </AuthorizeView>
                        <AuthorizeView Policy="@PolicyNames.Role">
                            <Authorized>
                                <MatNavItem Href="roles" Title="roles"><MatIcon Icon="@MatIconNames.Group"></MatIcon>&nbsp; Roles</MatNavItem>
                            </Authorized>
                        </AuthorizeView>
                    </MatNavSubMenuList>
                </MatNavSubMenu>
            </Authorized>
        </AuthorizeView>
    </Authorized>
</AuthorizeView>

当我的应用程序运行时,菜单中没有任何项目显示,只有主页和索赔项目不受AuthorizeView保护。

该问题是由于目前不支持Blazor读取以阵列形式发送的索赔

e、 g.用户:[“c”、“r”、“u”、“d”]

无法阅读

要纠正此问题,您需要添加ClaimsPrincipalFactory

e、 g

使用Microsoft.AspNetCore.Components.WebAssembly.Authentication;
使用Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
使用System.Linq;
使用System.Security.Claims;
使用System.Text.Json;
使用System.Threading.Tasks;
名称空间YourNameSpace
{
公共类ArrayCamsPrincipalFactory:AccountClaimsPrincipalFactory,其中TAccount:RemoteUserAccount
{
公共阵列AIMSPRINCIPALFactory(IAccessTokenProviderAccessor访问器)
:基本(存取器)
{ }
//当用户属于多个角色时,IS4返回一个带有序列化值数组的声明
//此类通过以正确的方式反序列化声明来改进原始工厂
public async override ValueTask CreateUserAsync(TAccount帐户、RemoteAuthenticationUserOptions选项)
{
var user=await base.CreateUserAsync(帐户,选项);
var claimsIdentity=(claimsIdentity)user.Identity;
如果(帐户!=null)
{
foreach(账户中的var kvp.AdditionalProperties)
{
var name=kvp.Key;
var值=kvp.值;
if(值!=null&&
(值为JsonElement元素&&element.ValueKind==JsonValueKind.Array))
{
claimsIdentity.RemoveClaim(claimsIdentity.FindFirst(kvp.Key));
var claims=element.EnumerateArray()
.Select(x=>newclaim(kvp.Key,x.ToString());
索赔性质。增加索赔(索赔);
}
}
}
返回用户;
}
}
}
然后在程序/启动中注册此项(取决于是否使用.core托管):

builder.Services.AddOidcAuthentication(选项=>
{
builder.Configuration.Bind(“oidc”,options.ProviderOptions);
})
.AddAccountClaimsPrincipalFactory();

了解Steve的问题后,我做了以下解决方案。 对那些跟随克里斯·圣蒂的人有用

我更新了我的方法来解析jwt中的声明,以分离所有声明的数组

private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
    var claims = new List<Claim>();
    var payload = jwt.Split('.')[1];
    var jsonBytes = ParseBase64WithoutPadding(payload);
    var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);

    keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);

    if (roles != null)
    {
        if (roles.ToString().Trim().StartsWith("["))
        {
            var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());
            foreach (var parsedRole in parsedRoles)
            {
               claims.Add(new Claim(ClaimTypes.Role, parsedRole));
            }
        }
        else
        {
            claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
        }
        keyValuePairs.Remove(ClaimTypes.Role);
    }
    claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
    for (int i = 0; i < claims.Count; i++)
    {
        var name = claims[i].Type;
        var value = claims[i].Value;
        if (value != null && value.StartsWith("["))
        {
            var array = JsonSerializer.Deserialize<List<string>>(value);
            claims.Remove(claims[i]);
            foreach (var item in array)
            {
                claims.Add(new Claim(name, item));
            }
        }
    }
    return claims;
}
private IEnumerable ParseClaimsFromJwt(字符串jwt)
{
var索赔=新列表();
var有效载荷=jwt.Split('.')[1];
var jsonBytes=parsebase64,不添加输出(有效负载);
var keyValuePairs=JsonSerializer.Deserialize(jsonBytes);
keyValuePairs.TryGetValue(ClaimTypes.Role、out对象角色);
if(角色!=null)
{
if(roles.ToString().Trim().StartsWith(“[”))
{
var parsedRoles=JsonSerializer.Deserialize(roles.ToString());
foreach(parsedRoles中的var parsedRole)
{
添加(新索赔(ClaimTypes.Role,parsedRole));
}
}
其他的
{
添加(新声明(ClaimTypes.Role,roles.ToString());
}
keyValuePairs.Remove(ClaimTypes.Role);
}
claims.AddRange(keyValuePairs.Select(kvp=>newclaims(kvp.Key,kvp.Value.ToString());
for(int i=0;i
我也有同样的问题..你解决了吗?嘿,Marshall,你的声明在示例中也像我的一样,一个声明有多个值吗?是的!我在很多方面都尝试过!一个具有多个值的声明类型,一个验证多个声明的扩展。我正在处理多个布局,我不知道这是否是问题…在home p上年龄我能够验证基于角色的策略。我只是不能对声明进行验证。您尝试过我刚才提供的解决方案吗?而且我认为您正在使用策略。是的,这是正确的,我认为无论您使用的是4还是否,此解决方案都有效。ClaimsPrincipalFactory所需的参考都是Microsoft的,而不是我独有的S4.我在示例中添加了名称空格
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;

namespace YourNameSpace
{
    public class ArrayClaimsPrincipalFactory<TAccount> : AccountClaimsPrincipalFactory<TAccount> where TAccount : RemoteUserAccount
    {
        public ArrayClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor)
        : base(accessor)
        { }


        // when a user belongs to multiple roles, IS4 returns a single claim with a serialised array of values
        // this class improves the original factory by deserializing the claims in the correct way
        public async override ValueTask<ClaimsPrincipal> CreateUserAsync(TAccount account, RemoteAuthenticationUserOptions options)
        {
            var user = await base.CreateUserAsync(account, options);

            var claimsIdentity = (ClaimsIdentity)user.Identity;

            if (account != null)
            {
                foreach (var kvp in account.AdditionalProperties)
                {
                    var name = kvp.Key;
                    var value = kvp.Value;
                    if (value != null &&
                        (value is JsonElement element && element.ValueKind == JsonValueKind.Array))
                    {
                        claimsIdentity.RemoveClaim(claimsIdentity.FindFirst(kvp.Key));

                        var claims = element.EnumerateArray()
                            .Select(x => new Claim(kvp.Key, x.ToString()));

                        claimsIdentity.AddClaims(claims);
                    }
                }
            }

            return user;
        }
    }
}
builder.Services.AddOidcAuthentication(options =>
        {
            builder.Configuration.Bind("oidc", options.ProviderOptions);
        })
        .AddAccountClaimsPrincipalFactory<ArrayClaimsPrincipalFactory<RemoteUserAccount>>();
private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
    var claims = new List<Claim>();
    var payload = jwt.Split('.')[1];
    var jsonBytes = ParseBase64WithoutPadding(payload);
    var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);

    keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);

    if (roles != null)
    {
        if (roles.ToString().Trim().StartsWith("["))
        {
            var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());
            foreach (var parsedRole in parsedRoles)
            {
               claims.Add(new Claim(ClaimTypes.Role, parsedRole));
            }
        }
        else
        {
            claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
        }
        keyValuePairs.Remove(ClaimTypes.Role);
    }
    claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
    for (int i = 0; i < claims.Count; i++)
    {
        var name = claims[i].Type;
        var value = claims[i].Value;
        if (value != null && value.StartsWith("["))
        {
            var array = JsonSerializer.Deserialize<List<string>>(value);
            claims.Remove(claims[i]);
            foreach (var item in array)
            {
                claims.Add(new Claim(name, item));
            }
        }
    }
    return claims;
}