IIS中使用ASP.NET应用程序在多域林中的Windows身份验证问题

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (57)

我正在尝试实现一个使用Windows身份验证的基于Web的Intranet项目。Web服务器(Windows 2012 Server)位于域A中,但我需要能够从林中任何域中的计算机访问该站点。我只是使用域A和B中的计算机来测试它。

在IIS 7.0中,我启用了Windows身份验证并禁用了所有其他身份验证,包括匿名身份验证。在web.config我有:

<authentication mode="Windows"></authentication>
<identity impersonate="true" />
<authorization>
  <deny users="?" />
</authorization>

经过身份验证的用户需要在AD组“TestGroup”中; 为了测试目的,我在web.config中删除了<allow groups =“TestGroup”/>; 我还在主页上添加了一些标签来显示我的用户ID,我所属的组,“TestGroup”的所有成员以及我是否是“TestGroup”的成员,jut用于调试目的。

我相信到目前为止我做的一切都是正确的。使用web.config:

  • 当我从域A中的PC访问时,我没有被提示登录(由于我已经登录到域A,因为我已经登录到域A),并且所有lebles都显示正确的数据。
  • 当我从域B中的PC访问时,我被要求登录(正确),用户ID标签正确显示我的ID,但没有显示我的用户ID的组和“TestGroup”中没有组成员。

如果我删除web.config中的标识部分:

  • 当从域A或域B中的PC访问时,用户ID标签显示“NT AUTHORITY / NETWORK SERVICE”,没有列为我所属的组(因为我现在显然是“NT Authority”),但是“TestGroup”的组成员“列出正确。从域B中的PC访问会正确弹出登录对话框。

如果我删除授权部分并在web.config中保留标识部分:

  • 我没有被要求从任何一个域的PC登录;
  • 从域A中的PC访问可以正确显示所有内容
  • 从域B中的PC访问,可以显示用户ID,但没有组成员身份,也没有列出“TestGroup”组的用户。

似乎为了能够显示正确的用户ID,我需要将模拟设置为true; 为了要求用户从域外登录PC,AI需要有授权部分,但两者一起似乎不能在域A之外的PC上工作。

这是我用来获取用户ID,用户组成员资格和组成员的内容:

WindowsIdentity wiUser = WindowsIdentity.GetCurrent();
string sID = wiUser.Name.ToUpper().Repl("DomainA\\", string.Empty);
string sGroupName = @"TestGroup";
List<string> lsGroups = Utils.GetUserADGroups(sID);
bool bTC = lsGroups.Contains(sGroupName);
StringCollection scGroupMembers = Utils.GetGroupMembers(Utils.DomainType., sGroupName);

static string adDomain = "USA.ABC.DEF.COM";
static string adContainer = "DC=USA,DC=abc,DC=def,DC=com";
static string adADPath = "LDAP://USA.abc.def.com";

public static List<string> GetUserADGroups(string UserName)
{
    List<string> lsGroups = new List<string>();

    try
    {
        PrincipalContext pc = new PrincipalContext(ContextType.Domain, adDomain, adContainer);
        UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, UserName);
        PrincipalSearchResult<Principal> psr = up.GetGroups(pc);

        foreach (Principal p in psr)
        {
            lsGroups.Add(p.Name);
        }
    }
    catch (Exception)
    {
    }
    return lsGroups;
}

public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
    DirectoryEntry de = new DirectoryEntry(adDSADPath);
    System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();

    try
    {
        //DirectoryEntry DirectoryRoot = new DirectoryEntry(sADPath);
        DirectorySearcher DirectorySearch = new DirectorySearcher(de, ("(CN=" + (strGroup + ")")));
        SearchResultCollection DirectorySearchCollection = DirectorySearch.FindAll();

        foreach (SearchResult DirectorySearchResult in DirectorySearchCollection)
        {
            ResultPropertyCollection ResultPropertyCollection = DirectorySearchResult.Properties;

            foreach (string GroupMemberDN in ResultPropertyCollection["member"])
            {
                DirectoryEntry DirectoryMember = new DirectoryEntry(("LDAP://" + GroupMemberDN));
                System.DirectoryServices.PropertyCollection DirectoryMemberProperties = DirectoryMember.Properties;
                object DirectoryItem = DirectoryMemberProperties["sAMAccountName"].Value;

                if (null != DirectoryItem)
                {
                    GroupMembers.Add(DirectoryItem.ToString());
                }
            }
        }
    }
    catch (Exception ex)
    {
    }
    return GroupMembers;
}

我也尝试使用它来查看用户是否是该组的成员,但如果我从域B中的PC访问该站点,则会抛出错误:

public static bool IsMember(string UserName, string GroupName)
{
    try
    {
        PrincipalContext pc = new PrincipalContext(ContextType.Domain, adDomain, adContainer);
        UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, UserName);
        PrincipalSearchResult<Principal> psr = up.GetGroups(pc);

        foreach (Principal result in psr)
        {
            if (string.Compare(result.Name, GroupName, true) == 0)
                return true;
        }
        return false;
    }
    catch (Exception e)
    { 
        throw e; 
    }
}
提问于
用户回答回答于

最终解决我的问题的方法是将方法中的功能包装在:

using (System.Web.Hosting.HostingEnvironment.Impersonate())
{
}

例如,我更改了原始帖子中的方法:

public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
    DirectoryEntry de = new DirectoryEntry(adDSADPath);
    System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();
...
}

至:

public static StringCollection GetGroupMembers(DomainType eDomainType, string strGroup)
{
    using (System.Web.Hosting.HostingEnvironment.Impersonate())
    {
        DirectoryEntry de = new DirectoryEntry(adDSADPath);
        System.Collections.Specialized.StringCollection GroupMembers = new System.Collections.Specialized.StringCollection();
        ...
    }
}

希望这能给别人带来一些悲伤,因为它给我带来了很多!

扫码关注云+社区

领取腾讯云代金券