模拟以更新 ASP.NET Forms 身份验证站点中的用户 AD 信息
我们有一个经过表单验证的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你的上下文/搜索根在哪里,告诉它你正在尝试连接到谁/你正在尝试搜索哪里?
前任。
如果你没有这个,那么根据 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.
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
我们自己的 @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.
处理 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.