Asp Net Core 3.1 自定义角色授权
Asp Net Core 3.1 Authorization by Custom Roles
我在 ASP Net Forum 上看到了对 net core 2.2 基本相同的问题的回答。
当我尝试为我的 net core 3.1 应用程序实施时,出现错误
System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity'
错误发生在 RoleAuthHandler.cs 尝试将 Identity 转换为 WindowsIdentity 时。
我想知道核心 2.2 和 3.1 之间是否有变化可以解释这一点,或者我做错了什么。任何帮助都会很棒。
Startup.cs 包含
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IAuthorizationHandler, RoleAuthHandler>();
services.AddAuthorization(options =>
options.AddPolicy(
Role.Admin,
policy => policy.AddRequirements(new RoleRequirement(Role.Admin))));
}
Role.cs
public static class Role
{
public const string Guest = "Guest";
public const string Admin = "Admin";
}
RoleRequirement.cs
public class RoleRequirement : IAuthorizationRequirement
{
public string[] Roles { get; }
public RoleRequirement(params string[] roles)
{
this.Roles = roles;
}
}
RoleAuthHandler.cs 包含
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var wi = (WindowsIdentity)context.User.Identity;
var groupSet = new HashSet<string>();
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
groupSet.Add(group.Translate(typeof(NTAccount)).ToString());
}
}
string[] userRoles = roleService.GetRolesForGroup(groupSet);
var intersectRoles = Enumerable.Intersect(userRoles, requirement.Roles, StringComparer.OrdinalIgnoreCase);
if (intersectRoles.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
控制器class
[Authorize]
[ApiController]
[Route("[controller]")]
public class InterestingController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Something Interesting";
}
}
@Sayah imad - 谢谢提醒。我曾在某处的 post 上看到过此解决方案,但由于我要查找的信息是 "what group does the user belong to" 而将其忽略。我没有意识到的是,该信息在 ClaimsIdentity 中可用。你的提及,让我三思而后行,我找到了我的答案:
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var claimsIdentity = (ClaimsIdentity)context?.User.Identity;
var userGroups = claimsIdentity.Claims
.Where(x => x.Type.Contains("groupsid", StringComparison.OrdinalIgnoreCase))
.ToList();
if (userGroups == null || !userGroups.Any())
{
return Task.CompletedTask;
}
var groupNames = new HashSet<string>();
foreach (var group in userGroups)
{
var groupName = new SecurityIdentifier(group.Value)
.Translate(typeof(NTAccount))
.ToString();
groupNames.Add(groupName);
}
var userRoles = this.authenticationService.GetRoles(groupNames.ToArray());
// If the user is an Admin, always allow
if (userRoles.Contains(Role.Admin))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
var intersectingRoles = Enumerable.Intersect(
userRoles,
requirement?.Roles,
StringComparer.OrdinalIgnoreCase);
if (intersectingRoles?.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
我在 ASP Net Forum 上看到了对 net core 2.2 基本相同的问题的回答。 当我尝试为我的 net core 3.1 应用程序实施时,出现错误
System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity'
错误发生在 RoleAuthHandler.cs 尝试将 Identity 转换为 WindowsIdentity 时。
我想知道核心 2.2 和 3.1 之间是否有变化可以解释这一点,或者我做错了什么。任何帮助都会很棒。
Startup.cs 包含
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IAuthorizationHandler, RoleAuthHandler>();
services.AddAuthorization(options =>
options.AddPolicy(
Role.Admin,
policy => policy.AddRequirements(new RoleRequirement(Role.Admin))));
}
Role.cs
public static class Role
{
public const string Guest = "Guest";
public const string Admin = "Admin";
}
RoleRequirement.cs
public class RoleRequirement : IAuthorizationRequirement
{
public string[] Roles { get; }
public RoleRequirement(params string[] roles)
{
this.Roles = roles;
}
}
RoleAuthHandler.cs 包含
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var wi = (WindowsIdentity)context.User.Identity;
var groupSet = new HashSet<string>();
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
groupSet.Add(group.Translate(typeof(NTAccount)).ToString());
}
}
string[] userRoles = roleService.GetRolesForGroup(groupSet);
var intersectRoles = Enumerable.Intersect(userRoles, requirement.Roles, StringComparer.OrdinalIgnoreCase);
if (intersectRoles.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
控制器class
[Authorize]
[ApiController]
[Route("[controller]")]
public class InterestingController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Something Interesting";
}
}
@Sayah imad - 谢谢提醒。我曾在某处的 post 上看到过此解决方案,但由于我要查找的信息是 "what group does the user belong to" 而将其忽略。我没有意识到的是,该信息在 ClaimsIdentity 中可用。你的提及,让我三思而后行,我找到了我的答案:
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var claimsIdentity = (ClaimsIdentity)context?.User.Identity;
var userGroups = claimsIdentity.Claims
.Where(x => x.Type.Contains("groupsid", StringComparison.OrdinalIgnoreCase))
.ToList();
if (userGroups == null || !userGroups.Any())
{
return Task.CompletedTask;
}
var groupNames = new HashSet<string>();
foreach (var group in userGroups)
{
var groupName = new SecurityIdentifier(group.Value)
.Translate(typeof(NTAccount))
.ToString();
groupNames.Add(groupName);
}
var userRoles = this.authenticationService.GetRoles(groupNames.ToArray());
// If the user is an Admin, always allow
if (userRoles.Contains(Role.Admin))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
var intersectingRoles = Enumerable.Intersect(
userRoles,
requirement?.Roles,
StringComparer.OrdinalIgnoreCase);
if (intersectingRoles?.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}