自定义角色的Asp Net Core 3.1授权 [英] Asp Net Core 3.1 Authorization by Custom Roles

查看:110
本文介绍了自定义角色的Asp Net Core 3.1授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在

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'

在RoleAuthHandler.cs尝试将Identity强制转换为WindowsIdentity时发生错误.

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

我想知道核心2.2和3.1之间是否有更改可以解释这一点,或者我做错了什么.任何帮助都会很棒.

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包含

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

RoleRequirement.cs

public class RoleRequirement : IAuthorizationRequirement
{
    public string[] Roles { get; }

    public RoleRequirement(params string[] roles)
    {
        this.Roles = roles;
    }
}

RoleAuthHandler.cs包含

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

控制器类

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

推荐答案

@Sayah imad-感谢您的提醒.我在某处的某个帖子上看到了此解决方案,因此将其解散了,因为我正在寻找的信息是用户所属的组".我没有意识到的是,该信息在ClaimsIdentity中可用.您的提及使我三思而后行,我找到了答案:

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

这篇关于自定义角色的Asp Net Core 3.1授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆