WindowsTokenRoleProvider 性能不佳

发布于 2024-08-15 18:28:53 字数 346 浏览 8 评论 0原文

我使用 WindowsTokenRoleProvider 来确定 ASP.NET Web 应用程序中的 Active Directory 组成员身份。

我的问题是性能不好,尤其是当用户位于多个组中时。例如,我在 253(!) 个组中,WindowsTokenRoleProvider 需要大约 150 秒来确定我所在的组。

我知道我可以使用缓存,这样就不会在后续操作中执行此操作请求用户,但显然在第一次点击时花费那么长时间是不可接受的。

我有什么选择?我可以强制 WindowsTokenRoleProvider 仅考虑某些组吗? (我只对5感兴趣)。

I'm using WindowsTokenRoleProvider to determine Active Directory group membership in an ASP.NET web application.

My problem is that performance is not good, especially when a user is in many groups. As an example, I am in 253(!) groups, and WindowsTokenRoleProvider is taking around 150 seconds to determine what groups I am in.

I know I can use caching so that this isn't done on subsequent requests for a user, but obviously it isn't acceptable to take that long on the first hit.

What are my options? Can I force WindowsTokenRoleProvider to only consider certain groups? (I'm only interested in 5).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各空 2024-08-22 18:28:53

一些测试表明我的问题是调用:

Roles.IsUserInRole(groupName)

正在访问 RoleProvider 中的方法 GetRolesForUser ,该方法正在检索用户所属的每个角色的详细信息。

但是调用:

Roles.Provider.IsUserInRole(groupName)

确定用户是否在组中 - 无需检索用户所在的每个角色的详细信息。

很奇怪,但看起来使用 Roles.Provider.IsUserInRole 可以解决我的问题。

* 更新*

事实证明,这只是部分解决方法;如果我在 web.comfig 中使用命令式权限检查或“允许”和“拒绝”,则 WindowsTokenRoleProvider 仍然会继续运行,并且缓慢获取用户所属的每个组的详细信息:o(

所以我的问题仍然存在...

* UPDATE *

我通过创建一个从 WindowsTokenRoleProvider 扩展的类并覆盖 GetRolesForUser 解决了这个问题,因此它只检查配置中指定的角色也包括缓存:

/// <summary>
/// Retrieve the list of roles (Windows Groups) that a user is a member of
/// </summary>
/// <remarks>
/// Note that we are checking only against each system role because calling:
/// base.GetRolesForUser(username);
/// Is _very_ slow if the user is in a lot of AD groups
/// </remarks>
/// <param name="username">The user to check membership for</param>
/// <returns>String array containing the names of the roles the user is a member of</returns>
public override string[] GetRolesForUser(string username)
{
    // Will contain the list of roles that the user is a member of
    List<string> roles = null;

    // Create unique cache key for the user
    string key = String.Concat(username, ":", base.ApplicationName);

    // Get cache for current session
    Cache cache = HttpContext.Current.Cache;

    // Obtain cached roles for the user
    if (cache[key] != null)
    {
        roles = new List<string>(cache[key] as string[]);
    }

    // Was the list of roles for the user in the cache?
    if (roles == null)
    {
        roles = new List<string>();

        // For each system role, determine if the user is a member of that role
        foreach (SystemRoleElement role in WebConfigSection.Settings.SystemRoles)
        {
            if (base.IsUserInRole(username, role.Name))
            {
                roles.Add(role.Name);
            }
        }

        // Cache the roles for 1 hour
        cache.Insert(key, roles.ToArray(), null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
    }

    // Return list of roles for the user
    return roles.ToArray();
}

Some testing has revealed that my problem is that calling:

Roles.IsUserInRole(groupName)

is accessing the method GetRolesForUser in the RoleProvider - which is retrieving details of every role the user is a member of.

But calling:

Roles.Provider.IsUserInRole(groupName)

determines whether or not the user is in the group - without retrieving the details of every role the user is in.

Weird, but it looks like using Roles.Provider.IsUserInRole will solve my problem.

* UPDATE *

It turns out that this is just a partial workaround; if I use imperative permission checks, or 'allow' and 'deny' in web.comfig, then WindowsTokenRoleProvider still goes and slowly gets details of every group the user is a member of :o(

So my question still stands...

* UPDATE *

I solved this by creating a class that extends from WindowsTokenRoleProvider and overriding GetRolesForUser so it only checks for membership of roles specified in the configuration. It includes caching too:

/// <summary>
/// Retrieve the list of roles (Windows Groups) that a user is a member of
/// </summary>
/// <remarks>
/// Note that we are checking only against each system role because calling:
/// base.GetRolesForUser(username);
/// Is _very_ slow if the user is in a lot of AD groups
/// </remarks>
/// <param name="username">The user to check membership for</param>
/// <returns>String array containing the names of the roles the user is a member of</returns>
public override string[] GetRolesForUser(string username)
{
    // Will contain the list of roles that the user is a member of
    List<string> roles = null;

    // Create unique cache key for the user
    string key = String.Concat(username, ":", base.ApplicationName);

    // Get cache for current session
    Cache cache = HttpContext.Current.Cache;

    // Obtain cached roles for the user
    if (cache[key] != null)
    {
        roles = new List<string>(cache[key] as string[]);
    }

    // Was the list of roles for the user in the cache?
    if (roles == null)
    {
        roles = new List<string>();

        // For each system role, determine if the user is a member of that role
        foreach (SystemRoleElement role in WebConfigSection.Settings.SystemRoles)
        {
            if (base.IsUserInRole(username, role.Name))
            {
                roles.Add(role.Name);
            }
        }

        // Cache the roles for 1 hour
        cache.Insert(key, roles.ToArray(), null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
    }

    // Return list of roles for the user
    return roles.ToArray();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文