【发布时间】:2013-02-03 11:45:40
【问题描述】:
我正在制作一个 ASP.NET (C#) 应用程序,该应用程序基本上是一个网关,用于为日常管理任务运行 Powershell 脚本。其中一些脚本使用 ActiveDirectory RSAT 模块,我发现其中一些 cmdlet 在通过网关调用时将无法正确运行,并且跟踪似乎暗示与域控制器的连接成功,但随后被关闭由 DC。
以下代码是一个 ASP.NET Web 表单,它有一个文本输入来指定用户名。基本上,它执行以下操作:
- 假设网络用户的身份(确认被powershell继承)
- 在该运行空间内创建一个 powershell 运行空间和管道
- 调用 Get-ADUser cmdlet 并将用户名作为 Identity 参数传递
-
通过将用户名读入表单上的输出元素来确认成功。
protected void LookupButton_Click( object sender, EventArgs e ) { WindowsImpersonationContext impersonationContext = ((WindowsIdentity)User.Identity).Impersonate(); Runspace runspace; Pipeline pipe; try { runspace = new_runspace(); runspace.Open(); pipe = runspace.CreatePipeline(); Command cmd = new Command("Get-ADUser"); cmd.Parameters.Add(new CommandParameter("Identity", text_username.Text)); pipe.Commands.Add(cmd); PSObject ps_out = pipe.Invoke().First(); output.Text = ps_out.Properties["Name"].Value.ToString(); } catch( Exception ex ) { error.Text = ex.ToString(); } finally { impersonationContext.Undo(); } } private Runspace new_runspace( ) { InitialSessionState init_state = InitialSessionState.CreateDefault(); init_state.ThreadOptions = PSThreadOptions.UseCurrentThread; init_state.ImportPSModule(new[] { "ActiveDirectory" }); return RunspaceFactory.CreateRunspace(init_state); }
有趣的部分是在 catch 块中暴露的错误消息中的具体措辞(强调我的):
System.Management.Automation.CmdletInvocationException:无法 联系服务器。这可能是因为该服务器不存在,它 当前已关闭,或者它没有 Active Directory Web 服务运行。 ---> Microsoft.ActiveDirectory.Management.ADServerDownException:无法 联系服务器。这可能是因为该服务器不存在,它 当前已关闭,或者它没有 Active Directory Web 服务运行。 ---> System.ServiceModel.CommunicationException: 套接字连接被中止。这可能是由错误引起的 处理您的消息或接收超时被超过 远程主机或底层网络资源问题。本地套接字 超时为“00:01:59.6870000”。 ---> System.IO.IOException:读取 操作失败,请参阅内部异常。 ---> System.ServiceModel.CommunicationException:套接字连接是 中止。这可能是由于处理您的消息时出错或 接收超时被远程主机或底层 网络资源问题。本地套接字超时为“00:01:59.6870000”。 ---> System.Net.Sockets.SocketException: 现有连接被远程主机强行关闭
上层异常表明存在超时,但下层异常没有表明超时(从命令返回仅需几秒钟)。在无法访问服务器的情况下,最低级别的异常消息说明了很多,但是这个特定的措辞让我认为这里存在某种身份验证(或其他安全)问题。
2013 年 2 月 19 日更新: 当使用here 描述的模拟方法时,脚本会按预期运行。这让我觉得问题可能是 Windows 身份验证提供的 WindowsIdentity 对象可能不适合基本上对 AD 进行 RPC 调用的脚本。不幸的是,我真的不希望放弃 Windows 身份验证,因为我必须在我的应用程序代码中处理用户的密码(这不是我想要的责任)。
我还没有找到任何关于 windows auth 到底在做什么或使用它会导致什么样的模拟的文档。是否可以在使用 Windows 身份验证时执行此操作,还是我必须要求用户给我他们的密码?
【问题讨论】:
标签: c# asp.net powershell active-directory impersonation