模拟在ASP.NET Forms身份验证站点中更新用户AD信息

时间:2011-07-29 13:06:31

标签: c# asp.net active-directory impersonation

我们有一个Forms Authenticated内部网,它会查询AD以进行登录,并在会话中存储Windows身份的副本,以便稍后在更新其AD条目时模拟用户。我们不能使用windows auth进行模仿(长篇故事)。

所以登录代码是:

[DllImport("advapi32.dll")]
        public static extern bool LogonUser(String
            lpszUsername, String lpszDomain,
            String lpszPassword, int dwLogonType, int
                dwLogonProvider, out int phToken);

        public bool LoginWindowsUser(String domain, String username, String pwd, HttpSessionStateBase session)
        {

            int ret = 0;
            int l_token1;
            bool loggedOn = LogonUser(username,
                domain, pwd,
                // Logon type=LOGON32_LOGON_NETWORK_CLEARTEXT.
            3,
                // Logon provider=LOGON32_PROVIDER_DEFAULT.
            0,
                // User token for specified user is returned 
                //here.
            out l_token1);

            if (loggedOn)
            {
                IntPtr token2 = new IntPtr(l_token1);
                var l_Wid = new WindowsIdentity(token2);


                session["WindowsIdentity"] = l_Wid;
            }
            return loggedOn;
        }

然后当我们需要更新用户的AD信息时,我们这样做:

public void UpdateUserProperty(string username, string propertyName, string propertyValue)
        {
            // Obtain the authenticated user's identity.
            var winId = (WindowsIdentity) ControllerContext.HttpContext.Session["WindowsIdentity"];
             // Start impersonating.
            using (WindowsImpersonationContext ctx = winId.Impersonate())
            {
                try
                {
                    var ds = new DirectorySearcher();
                    int ind = username.IndexOf("\\") + 1;
                    username = username.Substring(ind, username.Length - ind);

                    var filter = "(&(objectCategory=Person)(objectClass=user)";

                    if (!username.IsNullOrEmpty())
                    {
                        filter += "(samaccountname=*{0}*)".F(username);
                    }

                    filter += ")";

                    ds.Filter = filter;

                    foreach (var property in ADUserDetailsDisplay.LoadProperties())
                    {
                        ds.PropertiesToLoad.Add(property);
                    }

          ///////////// ERROR OCCURS AFTER NEXT LINE /////////////

                    var searchResult = ds.FindOne();

                    var userDirectoryEntry = searchResult.GetDirectoryEntry();

                    if (propertyValue.IsNullOrEmpty())
                    {
                        if (userDirectoryEntry.Properties[propertyName].Count > 0) userDirectoryEntry.Properties[propertyName].RemoveAt(0);
                    }
                    else if (userDirectoryEntry.Properties[propertyName].Count == 0)
                    {
                        userDirectoryEntry.Properties[propertyName].Add(propertyValue);
                    }
                    else
                    {
                        userDirectoryEntry.Properties[propertyName][0] = propertyValue;
                    }
                    userDirectoryEntry.CommitChanges();


                }
                catch (Exception ex)
                {
                    TempData.AddErrorMessage("Unable to update user: " + ex.Message);
                }
                finally
                {
                    // Revert impersonation.
                    if (ctx != null)
                        ctx.Undo();
                }
            }
            // Back to running under the default ASP.NET process identity.

        }

问题是我们收到以下错误:

无法更新用户:发生操作错误。

如果有人能引导我找到解决方案,我将非常感激。

使用IIS 7.5 Win2008 R2 ASP.NET MVC2

感谢。

3 个答案:

答案 0 :(得分:0)

我们自己的@dunnry解决了在ASP.NET下使用模拟运行System.DirectoryServices的步骤:

Ryann Dunn can help you here.

答案 1 :(得分:0)

处理AD有时候是PIA。

无论如何,请确保运行应用程序的应用程序池中设置的帐户对活动目录具有管理权限,以便在用户帐户中执行更改。

答案 2 :(得分:0)

您的上下文/ searchroot在哪里告诉您尝试连接到哪个/您要搜索的位置?

实施例。

// Bind to the users container.
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=users,DC=fabrikam,DC=com");
// Create a DirectorySearcher object.
DirectorySearcher mySearcher = new DirectorySearcher(entry);

如果你没有这个,那么根据MSDN,SearchRoot的默认值为null ... MSDN链接:http://msdn.microsoft.com/en-us/library/h9zyssd8.aspx