6

ユーザーがSQLServerを起動し、現在ログインしているドメインとは異なるドメインを使用してSQLServerに認証できるようにする必要があるシナリオがあります。したがって、これが設定される方法を明確にするために:

  1. ユーザーがオフィスに到着し、企業ドメインにログインします(簡単にするためにLOCALDOMAINと呼びます)。
  2. 彼らは別のドメインのリモートデータベースに接続したいと考えています(REMOTEDOMAINと呼びましょう)
  3. 最初に、彼らはREMOTEDOMAINへのVPNトンネルを確立するVPNツールを起動します(これはすべてテストされ、うまく機能します)
  4. ただし、デフォルトでSSMSを起動すると、LOCALDOMAINを介したWindows Authのみが許可され、REMOTEDOMAINを選択するオプションも利用できません。

私たちが発見したのは、コマンドラインからこれを実行すると機能するということです。

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);

ドメインが付加されている場合とされていない場合のユーザー名を試しましたが、どちらも機能しません。誰かが似たようなことをしようとしたことがありますか?ありがとう

4

3 に答える 3

0

次の行を削除する必要があります。

// 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正しい資格情報を持つ正しい実行可能ファイルを指しているため、その時点でへの呼び出しは成功するはずです。

于 2012-10-23T17:57:32.327 に答える
0

関連するかもしれないことをしました。あるドメインにログインし、別のドメインの共有フォルダのディレクトリ リストを取得しようとしました。これを行うには、LogonUser と Impersonate を使用します。コードは次のようになります (申し訳ありませんが、正確なシナリオを試すための SQL サーバーがありません)...

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

于 2012-10-25T20:02:38.960 に答える