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

发布于 2024-11-26 18:01:12 字数 3833 浏览 3 评论 0原文

我们有一个经过表单验证的 Intranet,它会查询 AD 的登录信息,并在会话中存储 Windows 身份的副本,以便稍后在更新 AD 条目时模拟用户。我们不能使用 Windows 身份验证进行模拟(长话短说)。

所以登录代码是:

[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

谢谢。

We have a Forms Authenticated intranet which querys AD for the login and stores a copy of the windows identity in the session in order to impersonate the user later when updating their AD entry. We can't use windows auth for impersonation (long story).

So the login code is:

[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;
        }

And then later when we need to update the user's AD info we do this:

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.

        }

The problem is that we are getting the following error:

Unable to update user: An operations error occurred.

If anyone can guide me to a solution I would be very grateful.

Using IIS 7.5 Win2008 R2 ASP.NET MVC2

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉薄对峙 2024-12-03 18:01:12

你的上下文/搜索根在哪里,告诉它你正在尝试连接到谁/你正在尝试搜索哪里?

前任。

// 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

Where is your context/searchroot that tells it who you are trying to connect to/where you are trying to search?

Ex.

// 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);

If you don't have this then according to MSDN the default value for SearchRoot is null...
MSDN Link: http://msdn.microsoft.com/en-us/library/h9zyssd8.aspx

晚雾 2024-12-03 18:01:12

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

Ryann Dunn可以在这里为您提供帮助。

Our own @dunnry has addressed the steps to get System.DirectoryServices running with impersonation under ASP.NET:

Ryann Dunn can help you here.

围归者 2024-12-03 18:01:12

处理 AD 有时就是 PIA。

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

Dealing with AD sometimes is a PIA.

Anyway, make sure that the account set in the Application Pool running your application has administrative rights on the active directory to perform changes in an user account.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文