C# IdentityServer4自定义身份验证处理程序可以';找不到用户的所有声明
我使用的是使用Asp.Net Identity和EntityFramework的IdentityServer4示例 我正在尝试使用基于声明/角色的自定义策略创建组控件 我的问题是,当我尝试在授权处理程序中获取用户声明时,我要查找的声明不会返回 查看SSMS中的数据库,我发现我创建的声明/角色位于名为“AspNetRoles”、“AspNetRoleClaims”、“AspNetUserClaims”的表中,我创建的用户位于“AspNetUsers”中,用户和角色的密钥位于“AspNetUserRoles”中。 当我调用获取用户授权声明时,声明列表似乎来自“IdentityClaims”表 在“AspNetClaims”中检查索赔似乎没有像在“IdentityClaims”中检查索赔那样简单的方法,因此我假设我在某个地方犯了错误 我已经四处寻找了一个解决方案,尝试了一些方法,但我找不到任何有效的方法 下面是我认为与问题最相关的代码,以及一些运行代码的截图 任何帮助都将不胜感激,提前谢谢C# IdentityServer4自定义身份验证处理程序可以';找不到用户的所有声明,c#,asp.net-identity,identityserver4,claims-based-identity,C#,Asp.net Identity,Identityserver4,Claims Based Identity,我使用的是使用Asp.Net Identity和EntityFramework的IdentityServer4示例 我正在尝试使用基于声明/角色的自定义策略创建组控件 我的问题是,当我尝试在授权处理程序中获取用户声明时,我要查找的声明不会返回 查看SSMS中的数据库,我发现我创建的声明/角色位于名为“AspNetRoles”、“AspNetRoleClaims”、“AspNetUserClaims”的表中,我创建的用户位于“AspNetUsers”中,用户和角色的密钥位于“AspNetUserR
代码 MvcClient.Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthorization(options =>
{
options.AddPolicy("AdminRights", policy =>
{
policy.Requirements.Add(new AdminRequirement());
policy.RequireAuthenticatedUser();
policy.AddAuthenticationSchemes("Cookies");
});
});
services.AddSingleton<IAuthorizationHandler, AdminRequirementHandler>();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token token"; // NEW CHANGE (token)
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1");
options.Scope.Add("AdminPermission"); // NEW CHANGE
options.Scope.Add("offline_access");
});
}
IdentityServerWithAspIdAndEF.Startup(在配置中最后调用)
图像 --编辑-- 我已经修改了你的代码,解决了这个问题 这是我的回购协议的链接 为了修复您的解决方案,我还更改了服务器身份验证响应类型:-
"code Id_token"
在config.cs中的MVC客户端设置中,我添加了以下属性:-
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true
我还从mvc客户端删除了adminpermission范围,因为它不是必需的
我还对AdminRequirementHandler.cs进行了一些修改,但我会让您在我的回购协议中探讨这一点
基本上,我们已经确保用户声明在身份令牌中,通过这样做,用户声明就可以在您的AdminRequirementHandler中访问
希望这有帮助。--编辑--
我已经修改了你的代码,解决了这个问题
这是我的回购协议的链接
为了修复您的解决方案,我还更改了服务器身份验证响应类型:-
"code Id_token"
在config.cs中的MVC客户端设置中,我添加了以下属性:-
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true
我还从mvc客户端删除了adminpermission范围,因为它不是必需的
我还对AdminRequirementHandler.cs进行了一些修改,但我会让您在我的回购协议中探讨这一点
基本上,我们已经确保用户声明在身份令牌中,通过这样做,用户声明就可以在您的AdminRequirementHandler中访问
希望这能有所帮助。乍一看,我可以看到MVC应用程序没有管理员权限声明,您正在将它们作为作用域进行请求。您需要显示客户端和服务器的配置……您好@Derek,谢谢您的回复。我已经添加了Config.cs代码。所有自定义声明和角色都已添加到IdS CreateSuperuser方法中,唯一的作用域是“api1”。您可以在配置身份验证的位置添加客户端代码吗?因此,您可以使用Asp Identity为UserStore设置Idsvr4。创建用户的声明存储在Asp Identity user claims表中,但是您在将它们传输到MVC客户端时遇到问题吗?我认为您只需要为MVC客户端配置添加更多的作用域,您是否可以显示MVC客户端的代码,将其配置为使用Identity Server 4作为身份验证服务器?@RuardvanElburg,我已添加/更新了问题的更多信息。我不知道你是否已经被自动通知了,所以我想我应该试着提及你。我一眼就能看出,MVC应用程序没有管理员权限声明,你是作为作用域请求它们的。您需要显示客户端和服务器的配置……您好@Derek,谢谢您的回复。我已经添加了Config.cs代码。所有自定义声明和角色都已添加到IdS CreateSuperuser方法中,唯一的作用域是“api1”。您可以在配置身份验证的位置添加客户端代码吗?因此,您可以使用Asp Identity为UserStore设置Idsvr4。创建用户的声明存储在Asp Identity user claims表中,但是您在将它们传输到MVC客户端时遇到问题吗?我认为您只需要为MVC客户端配置添加更多的作用域,您是否可以显示MVC客户端的代码,将其配置为使用Identity Server 4作为身份验证服务器?@RuardvanElburg,我已添加/更新了问题的更多信息。我不知道你是否已经被自动通知了,所以我想我应该试着提及你。谢谢你,这帮了大忙。遗憾的是,这个问题仍然没有解决,但已经取得了进展,我更新了问题以反映这一点。在我看来,客户端现在拥有权限,但用户仍然无法通过客户端访问声明,因为授权处理程序的日志中显示的数据与以前相同。您可以向我显示AdminRights要求的代码吗?是的,有3个。行政许可;创建、更新、删除。AdminPermission Read位于AspNetRoleClaims中,正如我所读到的,此处的声明会自动添加到具有该角色的任何用户。我还添加了我认为与问题相关的当前数据。为授权处理程序添加了代码。授权要求仅包含类定义。非常感谢您的帮助和时间。当我看到你的答案时,我刚刚设法让它自己工作起来,我只是没有弄清楚什么代码不再需要。谢谢你,它帮了我很多忙。遗憾的是,这个问题仍然没有解决,但已经取得了进展,我更新了问题以反映这一点。看起来
public class AdminRequirementHandler : AuthorizationHandler<AdminRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminRequirement requirement)
{
Console.WriteLine("User Identity: {0}", context.User.Identity);
Console.WriteLine("Role is 'Administrator'? : {0}", context.User.IsInRole("Administrator"));
Console.WriteLine("Identities of user:-");
foreach (var v in context.User.Identities)
{
Console.WriteLine("\tName: {0},\tActor: {1},\tAuthType: {2},\tIsAuth: {3}", v.Name, v.Actor, v.AuthenticationType, v.IsAuthenticated);
Console.WriteLine("\n\tClaims from Identity:-");
foreach (var c in v.Claims)
Console.WriteLine("\t\tType: {0},\tValue: {1},\tSubject: {2},\tIssuer: {3}", c.Type, c.Value, c.Subject, c.Issuer);
}
Console.WriteLine("Claims from other source:-");
foreach(Claim c in context.User.Claims)
{
Console.WriteLine("\t\tType: {0},\tValue: {1},\tSubject: {2},\tIssuer: {3}", c.Type, c.Value, c.Subject, c.Issuer);
}
Console.WriteLine("\n *** Starting Authroization. ***\n");
Claim
role = context.User.FindFirst("role"),
accessLevel = context.User.FindFirst("AdminPermission");
if (role == null)
Console.WriteLine("\tUser as no 'role' : '{0}'", role == null ? "null" : role.Value);
else
Console.WriteLine("\tUser has 'role' : '{0}'", role.Value);
if (accessLevel == null)
Console.WriteLine("\tUser has no claim 'AdminPermission' : '{0}'", accessLevel == null ? "null" : accessLevel.Value);
else
Console.WriteLine("\tUser has 'AdminPermission' : '{0}'", accessLevel.Value);
if (role != null && accessLevel != null)
{
if (role.Value == "Administrator" && accessLevel.Value == "Read")
context.Succeed(requirement);
}
else
Console.WriteLine("\n *** Authorization Failue. ***\n");
return Task.CompletedTask;
}
}
ApiClaims :
ApiResources : api1
ApiScopeClaims : AdminPermission, ApiScopeId = 2
ApiScopes : api1, ApiResourceId = 1
: AdminPermission, ApiResourceId = 1
ApiSecrets :
AspNetRoleClaims : AdminPermission, Read, RoleId = b2f03...
AspNetRoles : Administrator, b2f03...
: Customer, 779f7...
: Internal, 10d5d...
AspNetUserClaims : AdminPermission, Create, UserId = 8ee62...
: AdminPermission, Update, UserId = 8ee62...
: AdminPermission, Delete, UserId = 8ee62...
AspNetUserLogins :
AspNetUserRoles : UserId = 8ee62..., RoleId = b2f03...
AspNetUsers : superuser@mail.com, Id = 8ee62...
AspNetUserTokens :
ClientClaims :
ClientCorsOrigins :
ClientGrantTypes : hybrid, ClientId = 1
: client_credentials, ClientId = 1
: client_credentials, ClientId = 2
: password, ClientId = 3
ClientIdPRestrictions :
ClientPostLogoutRedirectUris : http://localhost:5002/signout-callback-oidc, ClientId = 1
ClientProperties :
ClientRedirectUris : http://localhost:5002/signin-oidc, ClientId = 1
Clients : mvc, AllowAccessTokenViaBrowser = 1, AllowOfflineAccess = 1, RequireConsent = 0
: client ...
: ro.client ...
ClientScopes : openid, ClientId = 1
: profile, ClientId = 1
: AdminPermission, ClientId = 1
ClientSecrets : Type = SharedSecret
IdentityClaims : Id IdentityResourceId Type
1 1 sub
2 2 name
3 2 family_name
4 2 given_name
5 2 middle_name
6 2 nickname
7 2 preferred_username
8 2 profile
9 2 picture
10 2 website
11 2 gender
12 2 birthdate
13 2 zoneinfo
14 2 locale
15 2 updated_at
16 3 AdminPermission
IdentityResources : openid
: profile
: AdminPermission
PersistedGrants : [8x] Type = refresh_token
"code Id_token"
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true