WindowsTokenRoleProvider的性能不佳

Coc*_*lla 9 asp.net performance active-directory roleprovider

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

我的问题是性能不好,特别是当用户在很多组中时.例如,我在253(!)组中,并且WindowsTokenRoleProvider花费大约150秒来确定我所在的组.

我知道我可以使用缓存,这样就不会对用户的后续请求进行此操作,但显然在第一次访问时需要花费很长时间.

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

Coc*_*lla 12

一些测试显示我的问题是调用:

Roles.IsUserInRole(groupName)
Run Code Online (Sandbox Code Playgroud)

正在访问方法GetRolesForUserRoleProvider-这是检索的每一个角色的细节的用户是其成员.

但是打电话:

Roles.Provider.IsUserInRole(groupName)
Run Code Online (Sandbox Code Playgroud)

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

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

*更新*

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

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

*更新*

我通过创建一个从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();
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案!这应该是WindowsTokenRoleProvider类的一部分.感谢您分享此代码. (3认同)