Asp.net core 基于多个角色的IdentityServer4基于角色的授权
我想使用IdentityServer4 hybrid实现多个基于角色的授权,一切都很好,但当我想这样使用时:Asp.net core 基于多个角色的IdentityServer4基于角色的授权,asp.net-core,.net-core,authorization,identityserver4,Asp.net Core,.net Core,Authorization,Identityserver4,我想使用IdentityServer4 hybrid实现多个基于角色的授权,一切都很好,但当我想这样使用时: [Authorize(Roles = "Admin,SalaryUser")] 它不允许我和拒绝访问 在我的场景中,用户有多个角色,如果角色有效,控制器应授予我访问权限,例如,在上面的代码中,控制器应授予这些用户访问权限: 用户具有SalaryUser角色,用户具有admin角色,用户同时具有admin和SalaryUser角色 以下是配置: .AddOpenIdConnect("oi
[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();
});
.AddOpenIdConnect(“oidc”,选项=>
{
options.signnscheme=“Cookies”;
选项。权限=权限;
options.RequireHttpsMetadata=false;
options.ClientId=ClientId;
options.ClientSecret=“secret”;
options.ResponseType=“代码id\U令牌”;
options.UseTokenLifetime=false;
options.SaveTokens=true;
options.GetClaimsFromUserInfoEndpoint=true;
options.claims.MapCustomJson(“角色”,jobj=>
{
IEnumerable values=jobj[“http://schemas.microsoft.com/ws/2008/06/identity/claims/role“].Values();
StringBuilder sb=新的StringBuilder();
foreach(值中的字符串val)
{
sb.追加(val+“,”);
}
将某人返回到字符串()TrimEnd(',');
});
选项。范围。添加(“api1”);
options.Scope.Add(“脱机访问”);
//选项。范围。添加(“角色”);
options.Events=new OpenIdConnectEvents()
{
OnUserInformation Received=异步用户信息ReceivedContext=>
{
//UserInformationReceivedContext.User.Remove(“地址”);
if(UserInformationReceivedContext.User.TryGetValue(“http://schemas.microsoft.com/ws/2008/06/identity/claims/role“,超出了JToken角色)
{
var索赔=新列表();
if(role.Type!=JTokenType.Array)
{
索赔。添加(新索赔(“http://schemas.microsoft.com/ws/2008/06/identity/claims/role“,(字符串)角色”);
}
其他的
{
foreach(角色中的var)
添加(新的索赔(“角色”,(字符串)r));
}
var id=用户信息ReceivedContext.Principal.Identity作为索赔实体;
id.AddClaims(索赔);
}
}
};
options.claims.MapAll();
});
您需要将JWT声明类型映射到Identity使用的声明类型
目前的问题是ASP.NET核心的标识系统依赖于
ClaimTypes.Role
常量
()至
确定用户的角色。但是,索赔人的姓名是:
与OpenID JWT令牌上的角色相对应的是role
。任何
当您需要合并OIDC标识和ASP.NET标识时,必须进行翻译
像这样的说法
我重写了一点代码,因为您可以在不使用JTokenType的情况下使用声明标识。虽然我没有时间对其进行彻底测试,但如果它不符合您的代码,请在向标识添加声明时将“role”替换为ClaimTypes.role
OpenIdConnectEvents CreateOpenIdConnectEvents()
{
返回新的OpenIdConnectEvents()
{
OnTicketReceived=context=>
{
var identity=context.Principal.identity作为索赔实体;
如果(标识!=null)
{
if(identity.HasClaim(c=>c.Type==“角色”))
{
foreach(identity.Claims.Where(c=>c.Type==“role”)中的var角色)
{
if(!context.Principal.HasClaim(c=>c.Type==ClaimTypes.Role&&c.Value==Role.Value))
{
AddClaim(新声明(ClaimTypes.Role、Role.Value));
}
}
}
}
返回Task.FromResult(0);
}
};
}
这样使用:
[Authorize(Roles = "Admin,SalaryUser")]
options.Events=new CreateOpenIdConnectEvents()
您不需要使用MapCustomJson
或在您收到的OnUserInformation
中手动映射索赔
如果jwt令牌中的声明是角色
而不是http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role
,您可以设置客户端应用程序的角色验证声明:
options.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "role"
};
另一种方法是在identity server应用程序上向颁发的令牌添加角色声明时,使用ClaimTypes.role
:
new Claim(ClaimTypes.Role, "Admin"),
这篇文章可能会解决这个问题。