[英]System.Diagnostics.Process.Start Exception for different user
[英]System.Diagnostics.Process.Start a process against a different domain
我们有一种情况,我们需要用户能够使用与当前登录的域不同的域来启动SQLServer并对其进行身份验证。 因此,要澄清设置方法:
我们发现,可以从命令行运行此命令:
RUNAS /user:REMOTEDOMAIN\AUserName /netonly "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Ssms.exe
它将提示消息“输入REMOTEDOMAIN \\ AUserName的密码:”,如果提供正确的密码,SSMS将启动并可以连接到远程数据库。 但是,当我尝试使用更好的接口在C#中执行相同的操作时,出现“登录失败:未知的用户名或错误的密码”,这是我的代码:
System.Security.SecureString password = new System.Security.SecureString();
foreach(char c in txtPassword.Text.ToCharArray()){
password.AppendChar(c);
}
System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo();
procInfo.Arguments = "/netonly";
procInfo.FileName = @"C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Ssms.exe"; ;
procInfo.Domain = "REMOTEDOMAIN";
procInfo.Verb = "runas";
procInfo.UserName = txtUsername.Text;
procInfo.Password = password;
procInfo.UseShellExecute = false;
System.Diagnostics.Process.Start(procInfo);
我尝试使用带或不带域名的用户名,但都无法使用。 是否有人尝试做类似的事情? 谢谢
您应该删除以下几行:
// Not passing /netonly to SMSS, it was passed to RunAs originally.
procInfo.Arguments = "/netonly";
// Again, SMSS is not getting the verb, it's being run
procInfo.Verb = "runas";
基本上,您将/netonly
参数传递给SMSS,而在命令行上,您正在运行runas
而不是SMSS 。 与动词相同,您没有运行runas
。
此时,对Start
的调用应该会成功,因为您将指向具有正确凭据的正确可执行文件。
我做了一些可能相关的事情。 我登录到一个域,并尝试获取另一域上共享文件夹的目录列表。 为此,我使用LogonUser和Impersonate。 该代码如下所示(抱歉,我没有SQL Server来尝试您的确切方案)...
public class Login : IDisposable
{
public Login(string userName, string domainName)
{
_userName = userName;
_domainName = domainName;
}
string _userName = null;
string _domainName = null;
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
WindowsImpersonationContext impersonatedUser = null;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
[DllImport("advapi32.dll", SetLastError = true, EntryPoint = "LogonUser")]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true, EntryPoint = "LogonUser")]
public static extern bool LogonUserPrompt(String lpszUsername, String lpszDomain, IntPtr lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
public void AccessShare(string password)
{
tokenHandle = IntPtr.Zero;
bool returnValue = LogonUser(_userName, _domainName, password,
LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
// Use the token handle returned by LogonUser.
WindowsIdentity newId = new WindowsIdentity(tokenHandle);
impersonatedUser = newId.Impersonate();
}
#region IDisposable Members
public void Dispose()
{
impersonatedUser.Undo();
// Free the tokens.
if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);
}
#endregion
}
我已经将它与Directory.GetDirectories(UNCPath)一起使用,其中该路径通向另一个域上的计算机,并且在那里可以正常工作。 我尚未尝试实现“ runas”。
我这样称呼它...
using(var login = new Login("myname","mydomain))
{
login.AccessShare("mypassword");
// do stuff
}
也许您可以使其适应您的问题。 LMK
我尝试了所有可以找到的各种用户模拟代码示例。 他们都没有工作。
最后,我想出了以下代码。 它使用/C
参数执行cmd.exe
,该参数Carries out the command specified by string and then terminates
。 我执行的命令是runas /netonly ...
不幸的是,必须手动输入密码。 我的下一步是研究向process
发送关键笔画。 我尝试重定向标准输入并将其写入,但是没有用。 我在某处读到,大多数密码提示仅接受直接来自键盘的输入。
同样,当SSMS打开时,“ 连接到服务器”对话框将显示您当前的域\\用户名,但它将使用您给runas
提供的身份进行身份验证。
最后,如果您的AD帐户已锁定,则在尝试连接到SQL Server之前不会收到错误消息。 我忽略了复制收到的错误消息,但没有提及该帐户已被锁定。
public static void RunAsNetonly(string username, string domain, string exePath)
{
var psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = $"/C runas /netonly /user:{domain}\\{username} \"{exePath}\"";
psi.UseShellExecute = false;
var process = Process.Start(psi);
// not sure if this is required
process.WaitForExit();
}
// usage example
public static void RunSSMS()
{
RunAsNetonly("walter", "domain123", @"C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\ssms.exe");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.