[IdentityServer4基于角色的多个角色授权

问题描述 投票:0回答:1

我想用IdentityServer4 Hybrid实现多个基于角色的授权,一切都很好,但是当我想这样使用时:

[Authorize(Roles = "Admin,SalaryUser")]

它不允许我访问并拒绝访问。

在我的情况下,用户具有多个角色,如果一个角色有效,则控制器应向我授予访问权限,例如,在以上代码中,控制器应向这些用户授予访问权限:用户具有SalaryUser角色,用户具有admin角色,用户同时具有Admin和SalaryUser角色。

这里是配置:

.AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = "Cookies";

                        options.Authority = authority;
                        options.RequireHttpsMetadata = false;
                        options.ClientId = clientId;
                        options.ClientSecret = "secret";
                        options.ResponseType = "code id_token";
                        options.UseTokenLifetime = false;
                        options.SaveTokens = true;
                        options.GetClaimsFromUserInfoEndpoint = true;





                        options.ClaimActions.MapCustomJson("role", jobj =>
                        {
                            IEnumerable<string> values = jobj["http://schemas.microsoft.com/ws/2008/06/identity/claims/role"].Values<string>();
                            StringBuilder sb = new StringBuilder();
                            foreach (string val in values)
                            {
                                sb.Append(val + ",");
                            }
                            return sb.ToString().TrimEnd(',');
                        });

                        options.Scope.Add("api1");
                        options.Scope.Add("offline_access");
                       // options.Scope.Add("roles");

                        options.Events = new OpenIdConnectEvents()
                        {

                            OnUserInformationReceived = async UserInformationReceivedContext =>
                            {
                                // UserInformationReceivedContext.User.Remove("address");

                                if (UserInformationReceivedContext.User.TryGetValue("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", out JToken role))
                                {
                                    var claims = new List<Claim>();
                                    if (role.Type != JTokenType.Array)
                                    {
                                        claims.Add(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", (string)role));
                                    }
                                    else
                                    {
                                        foreach (var r in role)
                                            claims.Add(new Claim("role", (string)r));
                                    }
                                    var id = UserInformationReceivedContext.Principal.Identity as ClaimsIdentity;
                                    id.AddClaims(claims);
                                }
                            }
                        };

                        options.ClaimActions.MapAll();
                    });
asp.net-core .net-core authorization identityserver4
1个回答
0
投票

您需要将JWT声明类型映射到Identity使用的声明类型。

当前的问题是ASP.NET Core的身份系统依赖于ClaimTypes.Role常数(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role)至确定用户的角色。但是,索赔的名称表明对应于OpenID JWT令牌上的角色就是role。任何当您需要合并OIDC身份和ASP.NET身份时,您必须进行翻译这样的主张。

我稍微重写了您的代码,因为您可以使用声明标识而无需使用JTokenType。尽管我没有时间对此进行全面测试,所以如果不遵循该代码,则可以在向身份添加声明时将“角色”替换为ClaimTypes.Role。

            OpenIdConnectEvents CreateOpenIdConnectEvents()
            {
                return new OpenIdConnectEvents()
                {
                    OnTicketReceived = context =>
                    {
                        var identity = context.Principal.Identity as ClaimsIdentity;
                        if (identity != null)
                        {
                            if (identity.HasClaim(c => c.Type == "role"))
                            {
                                foreach (var role in identity.Claims.Where(c => c.Type == "role"))
                                {
                                    if (!context.Principal.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == role.Value))
                                    {
                                        identity.AddClaim(new Claim(ClaimTypes.Role, role.Value));
                                    }
                                }
                            }

                        }
                        return Task.FromResult(0);
                    }
                };
            }

像这样使用:

options.Events = new CreateOpenIdConnectEvents()
© www.soinside.com 2019 - 2024. All rights reserved.