我正在使用WindowsTokenRoleProvide
r来确定ASP.NET Web应用程序中的Active Directory组成员身份。
我的问题是性能不佳,尤其是当用户处于多个组中时。例如,我在253(!)组中,WindowsTokenRoleProvider
大约需要150秒来确定我所在的组。
我知道我可以使用缓存,因此不会对后续的用户请求进行此操作,但显然在第一次访问时需要花费很长时间。
我有什么选择?我可以强制WindowsTokenRoleProvider
仅考虑某些群组吗? (我只对5感兴趣。)
答案 0 :(得分:12)
有些测试表明我的问题是调用:
Roles.IsUserInRole(groupName)
正在访问GetRolesForUser
中的方法RoleProvider
,该方法正在检索用户所属的每个角色的详细信息。
但是打电话:
Roles.Provider.IsUserInRole(groupName)
确定用户是否在该组中 - 不检索用户所在的每个角色的详细信息。
很奇怪,但看起来使用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();
}