【问题标题】:AspNet5 - Windows Authentication Get Group Name From ClaimsAspNet5 - Windows 身份验证从声明中获取组名
【发布时间】:2016-04-29 08:22:24
【问题描述】:

我有一个 asp.net5 项目设置来使用 Windows 身份验证。当我设置断点并查看用户时,我看到有一个包含组 SID 的声明数组。如何从声明中获取实际的组名?

我正在尝试使用他们所属的活动目录组来限制登录用户的窗口,并且正在努力设置它。

问题: 如何查看登录用户所属的活动目录组? 如何将 GroupSID 转换为组名? 我是否需要在 startup.cs 中包含任何内容以将某些组限制为 REST 服务调用?

我看到了基于登录用户手动设置声明的示例。我有兴趣使用 Windows 身份验证用户及其组来限制访问。

谢谢

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc


    【解决方案1】:

    你没有。不幸的是,这不是 Windows 身份验证的工作方式。您只能检查用户是否处于某个角色中(并且对此有政策要求),而不能枚举他们所处的角色 - 这需要目录服务并且尚未移植到核心。

    (需要注意的一点是,错误,User.IsInRole() 对于 Windows 身份现在已损坏。这将在 RC2 中修复)

    【讨论】:

    • 感谢您的回答。我现在可以拉下 RC2 吗?还是RC2还没有?是否像 asp.net 4 那样简单,我用 [Authenticate] 和 [Authorize("groupname")] 装饰一个休息方法,还是我必须编写一堆自定义代码?
    • 你还不能得到它。很快。一旦它起作用,是的,如果你不想使用策略,它会是一样的。你可以简单地做 [Authorize(Roles='')]
    • @blowdart 你有没有机会得到 github 问题,为什么 IsInRole() 被破坏了,或者碰巧知道它是如何被破坏的?
    【解决方案2】:

    您实际上仍然可以使用以下方法获取组名:

    var test = new System.Security.Principal.SecurityIdentifier("S-1-5-21-3290390516-4063083420-3538132138-1146").Translate(typeof(System.Security.Principal.NTAccount)).ToString();
    

    例如:

    var roles = ((ClaimsIdentity)_context.User.Identity).Claims.Where(q => q.Type == ClaimTypes.GroupSid).Select(q => q.Value);
    
    _logger.LogInformation($"Got {roles.Count()} roles");
    
    foreach (var role in roles)
    {
        var name = new System.Security.Principal.SecurityIdentifier(role).Translate(typeof(System.Security.Principal.NTAccount)).ToString();
        _logger.LogInformation($"Got role {name}");
    }
    

    输出:

    (namespace).Authorization.Handlers.SiteHandler: Information: Got 18 roles
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\Domain Users
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role Everyone
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted) Backend
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted) Dashboards
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role BUILTIN\Performance Log Users
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role BUILTIN\Users
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role NT AUTHORITY\INTERACTIVE
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role CONSOLE LOGON
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role NT AUTHORITY\Authenticated Users
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role NT AUTHORITY\This Organization
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role LOCAL
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\jira-users
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\jira-developers
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted)_PDMS_DE_ALL
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted)_PDMS_BE_ALL
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted)Developers
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted)_TEST
    (namespace).Authorization.Handlers.SiteHandler: Information: Got role (redacted)\(redacted)_PDMS_DB_ALL
    

    请注意,填充域角色可能需要一两秒时间。

    【讨论】:

    • 这真的很有帮助,直到 RC2 发布。好一个
    • 现在 1.0 已经发布,还有更好的方法吗?
    • 这种方法在 .NET 5 中仍然有效,但 Translate() 调用的性能成本非常。当遍历 UserClaims 时,Translate() 调用将占用大部分(约 75%)的处理时间。在用户可能有数十甚至数百个声明的环境中,这可能会导致显着放缓。
    【解决方案3】:

    另一种选择(类似于@JosephGarrone 的解决方案):

    private string[] GetGroups1()
    {
        var groups = new List<string>();
    
        var wi = (WindowsIdentity)User.Identity;
        if (wi.Groups != null)
        foreach (var group in wi.Groups)
        {
            try
            {                                
                groups.Add(group.Translate(typeof(NTAccount)).ToString());
            } catch (Exception) {
            // ignored
            }
        }
    
        groups.Sort(); // optional
        return groups.ToArray();
    }
    

    【讨论】:

      【解决方案4】:

      仅添加答案以帮助澄清最受好评的答案中的某些内容,因为我没有足够的代表来添加评论。

      该答案不会打印出实际的 AD 组名称。在 foreach 循环中将 role 替换为 name 将打印出 AD 组的名称。

      var roles = ((ClaimsIdentity)_context.User.Identity).Claims.Where(q => q.Type == ClaimTypes.GroupSid).Select(q => q.Value);
      
      _logger.LogInformation($"Got {roles.Count()} roles");
      
      foreach (var role in roles)
      {
          var name = new System.Security.Principal.SecurityIdentifier(role).Translate(typeof(System.Security.Principal.NTAccount)).ToString();
          _logger.LogInformation($"Got role {name}");
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-20
        • 2019-06-17
        • 1970-01-01
        相关资源
        最近更新 更多