【问题标题】:Asp Net Core 3.1 Authorization by Custom RolesAsp Net Core 3.1 自定义角色授权
【发布时间】:2020-02-08 01:41:15
【问题描述】:

我在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))));
}

角色.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;
}

控制器类

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

【问题讨论】:

  • 您能否检查这行代码 var wi = (WindowsIdentity)context.User.Identity 您应该在您的 CAS 中返回 ClaimsIdentity 您需要将您更改为 wi = (ClaimsIdentity)context.User.Identity 。

标签: c# asp.net-core-3.1


【解决方案1】:

@Sayah imad - 感谢您的提醒。我在某处的帖子上看到了这个解决方案,然后将其驳回,因为我正在寻找的信息是“用户属于哪个组”。我没有意识到该信息在 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;
    }

【讨论】:

  • 我在从 2.2 迁移到 3.1 时遇到了同样的问题,但是我看到的 ClaimsIdentity 有一个空的 Claims 集合并且没有 Name,那么我如何获取 Windows 用户信息?
  • @lesscode 我和你有同样的问题。我在 IIS 上运行了一个 asp.net 核心 Web 应用程序,并且该 Web 应用程序被配置为接受匿名身份验证。禁用此功能,仅保留 Windows 身份验证可用,确保声明是 Windows 身份之一。
  • @MortenNørgaard 不幸的是,我们的控制器混合了经过身份验证和匿名的端点,因此我们需要在 IIS 中启用这两种方案。我仍然认为这是一个重大更改,但我们能够通过将代码添加到我们的自定义处理程序的顶部来解决这个问题,该处理程序会提前失败经过身份验证的请求(将挑战返回给客户端)。详情在这里:github.com/dotnet/aspnetcore/discussions/…
猜你喜欢
  • 2020-05-27
  • 2019-07-31
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 2020-12-01
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多