[英]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.