Asp Net Core 3.1 Authorization by Custom Roles

狂风中的少年 提交于 2020-03-26 03:30:33

问题


I've seen basically the same question answered for net core 2.2 on ASP Net Forum. When I tried to implement for my net core 3.1 application, I'm getting an error

System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity'

The error happens on the RoleAuthHandler.cs trying to cast Identity to WindowsIdentity.

I'm wondering if there has been change between core 2.2 and 3.1 that explains this or I'm doing something wrong. Any help would be great.

Startup.cs contains

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 contains

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;
}

Controller class

[Authorize]
[ApiController]
[Route("[controller]")]
public class InterestingController : ControllerBase
{
    [HttpGet]
    public string Get()
    {
        return "Something Interesting";
    }
}

回答1:


@Sayah imad - Thanks for the reminder. I had seen this solution on a post somewhere and dismissed it because the information I was looking for was "what group does the user belong to". What I didn't realize was that the information was availabile in the ClaimsIdentity. Your mention, made me think twice about it and I found my answer:

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;
    }


来源:https://stackoverflow.com/questions/59905329/asp-net-core-3-1-authorization-by-custom-roles

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!