我有一个使用Windows身份验证的ASP.NET 3.5应用程序并实现了我们自己的RoleProvider。
问题是我们想要将对一组页面的访问限制为几千个用户,而不是逐个输入所有这些页面,我们发现它们属于一个AD组。
如果我们检查针对特定用户的成员资格的公共组是其直接成员,答案很简单但我遇到的问题是,如果该组是另一个组的成员,然后是另一个组的成员那么我的代码总是返回false。
例如:假设我们要检查用户是否是 E 组的成员,但用户不是*的直接成员E“,她是”A“的成员,”B“的成员确实是 E 的成员,因此用户是* E”的成员< / p>
我们所拥有的解决方案之一非常缓慢,尽管它给出了正确答案
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var group = GroupPrincipal.FindByIdentity(context, IdentityType.Name, "DL-COOL-USERS"))
{
var users = group.GetMembers(true); // recursively enumerate
return users.Any(a => a.Name == "userName");
}
}
原始解决方案以及我尝试使用.NET 3.5 System.DirectoryServices.AccountManagement工作,当用户是相关组的直接成员时,它确实有效,如下所示:
public bool IsUserInGroup(string userName, string groupName)
{
var cxt = new PrincipalContext(ContextType.Domain, "DOMAIN");
var user = UserPrincipal.FindByIdentity(cxt, IdentityType.SamAccountName, userName);
if (user == null)
{
return false;
}
var group = GroupPrincipal.FindByIdentity(cxt, groupName);
if (group == null)
{
return false;
}
return user.IsMemberOf(group);
}
最重要的是,我们需要检查成员资格,即使这些组在多个级别中嵌套。
非常感谢!
答案 0 :(得分:1)
由于您使用的是ASP.NET,因此限制访问的更简单的解决方案是在web.config中设置它,示例如下:
<configuration>
<location path="protected/url/path">
<system.web>
<authorization>
<allow roles="DOMAIN\group"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>
有关详细信息:http://msdn.microsoft.com/en-us/library/wce3kxhd.aspx和http://msdn.microsoft.com/en-us/library/b6x6shw7.aspx。
我在.NET 2.0应用程序中使用的代码,在与您相似的大森林中运行良好。
static bool IsUserInGroup(DirectoryEntry user, string groupName)
{
user.RefreshCache(new string[] {"tokenGroups"});
for (int i = 0; i < user.Properties["tokenGroups"].Count; i++) {
SecurityIdentifier sid = new SecurityIdentifier((byte[]) user.Properties["tokenGroups"][i], 0);
try {
NTuser nt = (NTuser) sid.Translate(typeof(NTuser));
if (nt.Value.ToLower().EndsWith("\\" + groupName.ToLower())) {
return true;
}
} catch (IdentityNotMappedException) {
continue;
}
}
return false;
}
答案 1 :(得分:1)
好吧,我不得不在广场外思考这个,幸运的是,通过调查AD我们发现所有3000多个必须看到页面的人在自定义AD属性中共享一个关键字。所以我所要做的就是从AD加载对象并查看它。最终结果客户非常高兴!目前这似乎是一个肮脏的解决方案,但一如既往,这是完美的工作,我们必须继续其他事情!
目前我们正在通过试点计划和我们得到的任何错误,我们希望它们冒出来并得到通知,以便我们采取行动。
public static bool IsEmployeeCoolEnoughToSeePages(string userName)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentNullException("Current user's Username cannot be null");
}
using (var searcher = new DirectorySearcher(("LDAP://YOURDOMAIN.com")))
{
searcher.Filter = string.Format("(&(objectCategory=user)(samAccountName={0}))", ariseUserName);
SearchResultCollection searchResultCollection = searcher.FindAll();
if (searchResultCollection.Count == 1)
{
var values = searchResultCollection[0].Properties["title"];
if (values.Count == 1)
{
return values[0].ToString().StartsWith("_COOLNES_");
}
}
return false;
}
}