在活动目录中保存用户列表时调用错误
本文关键字:列表 调用 错误 用户 保存 活动 | 更新日期: 2023-09-27 18:17:46
我有一个问题,从csv文件保存用户,在活动目录中,使用ASP。Net MVC 4应用程序(框架4.5)。问题是第一个用户被正确地保存了,但是第二个用户返回了这个错误:
'/ADManagementStudio'应用程序出现服务器错误。
访问被拒绝。HRESULT异常:0x80070005(E_ACCESSDENIED))
描述:在执行过程中发生未处理的异常当前的web请求。请查看堆栈跟踪了解更多信息有关错误及其在代码中的起源的信息。
Exception Details: System。UnauthorizedAccessException:访问是否认。(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
ASP。NET未被授权访问所请求的资源。[…]
[…]
源错误:
的过程中产生了一个未处理的异常当前的web请求。关于来源和地点的信息可以使用下面的异常堆栈跟踪来识别异常。堆栈跟踪:
[UnauthorizedAccessException: Access is denied.](例外HRESULT: 0x80070005 (E_ACCESSDENIED))]
[TargetInvocationException:异常已被目标抛出。一个调用。)
System.DirectoryServices.DirectoryEntry。methodName Invoke(字符串,Object[] args) +630438
ADManagementStudio.Web.Controllers.UsersController.AddUsers (HttpPostedFileBase文件)+ 1437
ADManagementStudio.Web.Controllers.UsersController.CSV (HttpPostedFileBaselambda_method(Closure, ControllerBase, Object[]) +127System.Web.Mvc.ReflectedActionDescriptor.Execute (ControllerContext控制器上下文,字典2 parameters) +248
参数)+ 39
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
System.Web.Mvc.Async灵活;> c_ DisplayClass39.b _33 ()+ 120 System.Web.Mvc.Async灵活;> c_ DisplayClass4f.b _49 ()+ 452 System.Web.Mvc.Async灵活;> c_ DisplayClass37。b_36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async灵活;> c_ DisplayClass2a.b _20 ()+ 31 System.Web.Mvc.Async灵活;> c_ DisplayClass25.b _22 (IAsyncResultasyncResult) + 230
System.Web.Mvc灵活;> c_ DisplayClass1d.b _18 (IAsyncResultasyncResult) + 28
System.Web.Mvc.Async灵活;> c_ DisplayClass4.b _3 (IAsyncResult+15 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult .asyncResult) + 53
System.Web.Mvc.Async灵活;> c_ DisplayClass4.b _3 (IAsyncResult基于"增大化现实"技术)+ 15
System.Web.Mvc灵活;> c_ DisplayClass8.b _3 (IAsyncResultasyncResult) + 42
System.Web.Mvc.Async灵活;> c_ DisplayClass4.b _3 (IAsyncResult基于"增大化现实"技术)+ 15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute ()+ 606 System.Web.HttpApplication。ExecuteStep(IExecutionStep step, Boolean&completedSynchronously) + 288
我正在使用网络模拟。配置,但我认为这是有趣的,只有第一个用户被保存和其他没有,有什么不同?(或者我只是因为我的糟糕经验而忽略了它)
下面是函数的代码:private string AddUsers(HttpPostedFileBase file)
{
string tempFileName = string.Format("{0}_{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
string filePath = Path.Combine(Server.MapPath("~/AD_App_Data/temp"), tempFileName);
file.SaveAs(filePath);
FileInfo tempFileInfo = new FileInfo(filePath);
List<string[]> tempFileData = new List<string[]>();
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader(tempFileInfo.FullName, true))
{
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
string[] splitter = line.Split(';');
lines.Add(line);
tempFileData.Add(splitter);
}
}
tempFileInfo.Delete();
if ((tempFileData[0][0].ToLower() != "samaccountname") ||
(tempFileData[0][1].ToLower() != "displayname"))
{
return "Error! sAMAccountName or displayName fields not found!";
}
try
{
string LDAPContextPath = string.Format(
"LDAP://{0}/{1}",
ActiveDirectoryManage.GetServerName(),
ActiveDirectoryManage.GetLDAPUserPath());
List<string> newUsersPassword = new List<string>();
using (DirectoryEntry context = new DirectoryEntry(LDAPContextPath, "Administrator", "abcd,1234"))
{
foreach (string[] data in tempFileData.Skip(1))
{
using (DirectoryEntry userEntry = context.Children.Add(string.Format("CN={0}", data[1]), "user"))
{
userEntry.Properties["sAMAccountName"].Value = data[0];
userEntry.CommitChanges();
for (int i = 1; i < data.Length; i++)
{
int number;
if (int.TryParse(data[i], out number))
{
userEntry.Properties[tempFileData[0][i]].Value = number;
}
else
{
userEntry.Properties[tempFileData[0][i]].Value = data[i];
}
userEntry.CommitChanges();
}
string newPassword = Membership.GeneratePassword(12, 0);
userEntry.Invoke("SetPassword", newPassword);
userEntry.CommitChanges();
newUsersPassword.Add(newPassword);
userEntry.Properties["userAccountControl"].Value = 512;
userEntry.CommitChanges();
}
}
Thread.Sleep(1000);
}
string timestamp = string.Format(
"{0}{1}{2}-{3}{4}{5}",
DateTime.Today.Hour, DateTime.Today.Minute, DateTime.Today.Second,
DateTime.Today.Day, DateTime.Today.Month, DateTime.Today.Year);
string doneFileName = string.Format("{0}_{1}.csv", file.FileName, timestamp);
string donePath = Path.Combine(Server.MapPath("~/AD_App_Data/done"), doneFileName);
using (StreamWriter writer = new StreamWriter(donePath))
{
writer.WriteLine(AppendPassword(lines[0], "password"));
for (int i = 1; i < lines.Count; i++)
{
writer.WriteLine(AppendPassword(lines[i], newUsersPassword[i - 1]));
}
}
return doneFileName;
}
catch (DirectoryServicesCOMException ex)
{
return "Error! Exception! " + ex.Message;
}
}
谢谢你的忠告
如果使用模拟,则需要确保被模拟的用户具有在活动目录中修改/创建对象的足够权限。如果模拟的用户不是域管理员或没有自定义权限集,则几乎不会出现这种情况。
我建议您放弃模拟,或者将应用程序池作为在活动目录中具有有限权限的域帐户运行(考虑这里的最小权限,只给它完成其工作所需的权限),或者在代码中手动创建一个模拟上下文,其中域帐户具有与建议的应用程序池帐户相同的限制。
在这个SO回答中有几个链接可以帮助您在代码中模拟另一个用户。
好了,伙计们,我终于成功了!由于某些原因,现在我忽略了,我使用编程模拟的用户有足够的权限来管理AD在每次迭代。
这里是描述如何以编程方式实现服务器端模拟的页面的链接。
下面是我的用法:
private string AddUsers(HttpPostedFileBase file)
{
string tempFileName = string.Format("{0}_{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
string filePath = Path.Combine(Server.MapPath("~/AD_App_Data/temp"), tempFileName);
file.SaveAs(filePath);
FileInfo tempFileInfo = new FileInfo(filePath);
List<string[]> tempFileData = new List<string[]>();
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader(tempFileInfo.FullName, true))
{
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
string[] splitter = line.Split(';');
lines.Add(line);
tempFileData.Add(splitter);
}
}
tempFileInfo.Delete();
if ((tempFileData[0][0].ToLower() != "samaccountname") ||
(tempFileData[0][1].ToLower() != "displayname"))
{
return "Error! sAMAccountName or displayName fields not found!";
}
List<string> users = new List<string>();
try
{
string LDAPContextPath = string.Format(
"LDAP://{0}/{1}",
ActiveDirectoryManage.GetServerName(),
ActiveDirectoryManage.GetLDAPUserPath());
List<string> newUsersPassword = new List<string>();
foreach (string[] data in tempFileData.Skip(1))
{
if (impersonateValidUser("Administrator", ActiveDirectoryManage.GetDomainName(), "abcd,1234"))
{
using (DirectoryEntry context = new DirectoryEntry(LDAPContextPath, "Administrator", "abcd,1234"))
{
users.Add(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
using (DirectoryEntry userEntry = context.Children.Add(string.Format("CN={0}", data[1]), "user"))
{
userEntry.Properties["sAMAccountName"].Value = data[0];
userEntry.CommitChanges();
for (int i = 1; i < data.Length; i++)
{
int number;
if (int.TryParse(data[i], out number))
{
userEntry.Properties[tempFileData[0][i]].Value = number;
}
else
{
userEntry.Properties[tempFileData[0][i]].Value = data[i];
}
userEntry.CommitChanges();
}
string newPassword = Membership.GeneratePassword(12, 0);
userEntry.Invoke("SetPassword", newPassword);
userEntry.CommitChanges();
newUsersPassword.Add(newPassword);
userEntry.Properties["userAccountControl"].Value = 512;
userEntry.CommitChanges();
}
}
undoImpersonation();
}
else
{
return "Error! Impersonation Failed";
}
}
string timestamp = string.Format(
"{0}{1}{2}-{3}{4}{5}",
DateTime.Today.Hour, DateTime.Today.Minute, DateTime.Today.Second,
DateTime.Today.Day, DateTime.Today.Month, DateTime.Today.Year);
string doneFileName = string.Format("{0}_{1}.csv", file.FileName, timestamp);
string donePath = Path.Combine(Server.MapPath("~/AD_App_Data/done"), doneFileName);
using (StreamWriter writer = new StreamWriter(donePath))
{
writer.WriteLine(AppendPassword(lines[0], "password"));
for (int i = 1; i < lines.Count; i++)
{
writer.WriteLine(AppendPassword(lines[i], newUsersPassword[i - 1]));
}
}
return doneFileName;
}
catch (Exception ex)
{
string error = "Error! Exception! " + ex.Message + "'n'n";
foreach (string s in users)
{
error = error + s + "'n'n";
}
return error;
}
}
希望这篇文章能对大家有所帮助!