身份服务器4。每个用户使用 2 个角色
IdentityServer4. Using 2 roles per user
我正在使用 IdentityServer4 和 MVC 客户端。我的问题是每个用户只能使用 1 个以上的角色。在下面的示例中,我有 2 个控制器,每个控制器都有其授权。如果 1 个用户在寄存器中有 2 个角色,他将拒绝两个角色的访问。
当您只为用户保留 1 个角色时,它工作得很好
Config.cs (IDS4)
public static IEnumerable<IdentityResource> Ids =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Phone(),
new IdentityResource("role", "role", new List<string> { "role" }),
};
new Client
{
ClientId = "mvc",
ClientName = "MVC App",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
RequireConsent = false,
RedirectUris = { mvcURL + "/signin-oidc" },
FrontChannelLogoutUri = mvcURL + "/signout-oidc",
PostLogoutRedirectUris = { mvcURL + "/signout-callback-oidc" },
//AllowOfflineAccess = true,
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone,
"api", "role"
}
},
ProfileService.cs (IDS4)
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var claims = principal.Claims.ToList();
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
// Add custom claims in token here based on user properties or any other source
claims.Add(new Claim("id_user", user.Id.ToString()));
claims.Add(new Claim("name", user.Name));
claims.Add(new Claim("email", user.Email.ToString()));
claims.Add(new Claim("role", user.role.ToString()));
if (_userManager.SupportsUserRole)
{
var roles = await _userManager.GetRolesAsync(user);
foreach (var roleName in roles)
{
claims.Add(new Claim(JwtClaimTypes.Role, roleName));
if (_roleManager.SupportsRoleClaims)
{
var role = await _roleManager.FindByNameAsync(roleName);
if (role != null)
claims.AddRange(await _roleManager.GetClaimsAsync(role));
}
}
}
context.IssuedClaims = claims;
}
Startup.cs (MVC)
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = Configuration.GetSection("ids_URI").Value;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = OpenIdConnectResponseType.Code;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("role");
options.SaveTokens = true;
options.ClaimActions.DeleteClaim("sid");
options.ClaimActions.DeleteClaim("idp");
options.ClaimActions.MapUniqueJsonKey("role", "role", "role");
options.TokenValidationParameters.RoleClaimType = "role";
});
控制器 1 (MVC)
[Authorize(Roles = "CANCELAMENTO")]
public class CancelamentoController : Controller
控制器 2 (MVC)
[Authorize(Roles = "ABASTECIMENTO")]
public class AbastecimentoController : Controller
在 AspNetUserRoles table 我有 2 个用户角色
用户对象来自角色:
Claims [IEnumerable]:{System.Security.Claims.ClaimsPrincipal.<get_Claims>d__22}
Membros não públicos
Visualização dos Resultados:Expandir a Visualização dos Resultados vai enumerar o IEnumerable
[0] [Claim]:{s_hash: 6WmMG-GghFBT9LCigeOnnw}
[1] [Claim]:{sub: 64637127-9e46-46e2-ad51-47297a52d483}
[2] [Claim]:{auth_time: 1641251760}
[3] [Claim]:{amr: pwd}
[4] [Claim]:{name: NOME}
[5] [Claim]:{given_name: SOBRENOME}
[6] [Claim]:{email: NOME@MAIL.COM}
[8] [Claim]:{role: ["ABASTECIMENTO","CANCELAMENTO"]}
有什么想法吗?
谢谢
我有同样的问题,我改变了
options.ClaimActions.MapUniqueJsonKey("role", "role", "role");
至
options.ClaimActions.MapJsonKey("role", "role", "role");
用户对象将是这样的:
[8] [Claim]:{role: "ABASTECIMENTO"}
[9] [Claim]:{role: "CANCELAMENTO"}
使用这种方法 User.IsInRole("role name");
效果很好。
我的 StartUp.cs 在 MVC 中:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.Scope.Add("email");
options.Scope.Add("roles");
options.ClaimActions.DeleteClaim("sid");
options.ClaimActions.DeleteClaim("idp");
options.ClaimActions.DeleteClaim("s_hash");
options.ClaimActions.DeleteClaim("auth_time");
options.ClaimActions.MapJsonKey("role", "role");
options.Scope.Add("api1");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
Config.cs 在 IDS4 中:
public static class Config
{
public static IEnumerable<IdentityResource> IdentityResources =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource("roles", "Your role(s)", new List<string>() { "role" })
};
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope>
{
new ApiScope("api1", "My API")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "mvc",
ClientName = "Application Web",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets = { new Secret("secret".Sha256()) },
RequirePkce = false,
AllowRememberConsent = false,
RedirectUris = { "https://localhost:5003/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1",
"roles"
}
}
};
}
我正在使用 IdentityServer4 和 MVC 客户端。我的问题是每个用户只能使用 1 个以上的角色。在下面的示例中,我有 2 个控制器,每个控制器都有其授权。如果 1 个用户在寄存器中有 2 个角色,他将拒绝两个角色的访问。
当您只为用户保留 1 个角色时,它工作得很好
Config.cs (IDS4)
public static IEnumerable<IdentityResource> Ids =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Phone(),
new IdentityResource("role", "role", new List<string> { "role" }),
};
new Client
{
ClientId = "mvc",
ClientName = "MVC App",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
RequireConsent = false,
RedirectUris = { mvcURL + "/signin-oidc" },
FrontChannelLogoutUri = mvcURL + "/signout-oidc",
PostLogoutRedirectUris = { mvcURL + "/signout-callback-oidc" },
//AllowOfflineAccess = true,
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone,
"api", "role"
}
},
ProfileService.cs (IDS4)
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var claims = principal.Claims.ToList();
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
// Add custom claims in token here based on user properties or any other source
claims.Add(new Claim("id_user", user.Id.ToString()));
claims.Add(new Claim("name", user.Name));
claims.Add(new Claim("email", user.Email.ToString()));
claims.Add(new Claim("role", user.role.ToString()));
if (_userManager.SupportsUserRole)
{
var roles = await _userManager.GetRolesAsync(user);
foreach (var roleName in roles)
{
claims.Add(new Claim(JwtClaimTypes.Role, roleName));
if (_roleManager.SupportsRoleClaims)
{
var role = await _roleManager.FindByNameAsync(roleName);
if (role != null)
claims.AddRange(await _roleManager.GetClaimsAsync(role));
}
}
}
context.IssuedClaims = claims;
}
Startup.cs (MVC)
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = Configuration.GetSection("ids_URI").Value;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = OpenIdConnectResponseType.Code;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("role");
options.SaveTokens = true;
options.ClaimActions.DeleteClaim("sid");
options.ClaimActions.DeleteClaim("idp");
options.ClaimActions.MapUniqueJsonKey("role", "role", "role");
options.TokenValidationParameters.RoleClaimType = "role";
});
控制器 1 (MVC)
[Authorize(Roles = "CANCELAMENTO")]
public class CancelamentoController : Controller
控制器 2 (MVC)
[Authorize(Roles = "ABASTECIMENTO")]
public class AbastecimentoController : Controller
在 AspNetUserRoles table 我有 2 个用户角色
用户对象来自角色:
Claims [IEnumerable]:{System.Security.Claims.ClaimsPrincipal.<get_Claims>d__22}
Membros não públicos
Visualização dos Resultados:Expandir a Visualização dos Resultados vai enumerar o IEnumerable
[0] [Claim]:{s_hash: 6WmMG-GghFBT9LCigeOnnw}
[1] [Claim]:{sub: 64637127-9e46-46e2-ad51-47297a52d483}
[2] [Claim]:{auth_time: 1641251760}
[3] [Claim]:{amr: pwd}
[4] [Claim]:{name: NOME}
[5] [Claim]:{given_name: SOBRENOME}
[6] [Claim]:{email: NOME@MAIL.COM}
[8] [Claim]:{role: ["ABASTECIMENTO","CANCELAMENTO"]}
有什么想法吗?
谢谢
我有同样的问题,我改变了
options.ClaimActions.MapUniqueJsonKey("role", "role", "role");
至
options.ClaimActions.MapJsonKey("role", "role", "role");
用户对象将是这样的:
[8] [Claim]:{role: "ABASTECIMENTO"}
[9] [Claim]:{role: "CANCELAMENTO"}
使用这种方法 User.IsInRole("role name");
效果很好。
我的 StartUp.cs 在 MVC 中:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.Scope.Add("email");
options.Scope.Add("roles");
options.ClaimActions.DeleteClaim("sid");
options.ClaimActions.DeleteClaim("idp");
options.ClaimActions.DeleteClaim("s_hash");
options.ClaimActions.DeleteClaim("auth_time");
options.ClaimActions.MapJsonKey("role", "role");
options.Scope.Add("api1");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
Config.cs 在 IDS4 中:
public static class Config
{
public static IEnumerable<IdentityResource> IdentityResources =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource("roles", "Your role(s)", new List<string>() { "role" })
};
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope>
{
new ApiScope("api1", "My API")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "mvc",
ClientName = "Application Web",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets = { new Secret("secret".Sha256()) },
RequirePkce = false,
AllowRememberConsent = false,
RedirectUris = { "https://localhost:5003/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1",
"roles"
}
}
};
}