9

数日前に質問をしました(Windows認証を使用した非ドメインマシンからのSQL Server 2005へのアクセス)。興味深いが、役に立たない提案がありました。もう一度質問したいのですが、私の制約が何であるかを明確にしてください。

マシンがSQLServer2005を実行していて、Windows認証のみをサポートするように構成されているWindowsドメインがあります。同じネットワーク上のマシンでC#クライアントアプリケーションを実行したいのですが、ドメイン上にはなく、SQLServer2005インスタンス上のデータベースにアクセスします。

どちらのマシンでもOSまたはSQLServerユーザーを作成または変更することはできません。また、アクセス許可や偽装を変更することも、ルーン文字を使用することもできません。

サーバー名、データベース名、ユーザー名(domain \ userの形式)、およびパスワードの4つのパラメーターのみを使用して、SQLServerデータベースに接続できるPerlおよびJavaアプリケーションを作成できることを知っています。

C#では、さまざまなことを試しました。

string connectionString = "Data Source=server;Initial Catalog=database;User Id=domain\user;Password=password";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();

統合セキュリティをtrueとfalseに設定しようとしましたが、何も機能していないようです。私がやろうとしていることは、C#では単純に不可能ですか?

助けてくれてありがとう、マーティン

4

7 に答える 7

9

あるドメインのマシンで実行し、信頼できる接続を使用して別のドメインの SQL サーバーで認証する必要があるツールを作成していたときに、同様の問題がありました。この件について私が見つけたものはすべて、それは不可能だと言いました。代わりに、ドメインに参加する、SQL 認証を使用する、Kerberos と呼ばれるチャプターに参加する、またはネットワーク担当者に信頼関係をセットアップしてもらうなど、いくつかの選択肢を挙げる必要があります。

問題は、SSMSでそれを証明したので、RUNASを使用して何らかの方法で動作させることができることを知っていたということです:

C:\WINDOWS\system32\runas.exe /netonly /savecred /user:megacorp\joe.bloggs "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\SqlWb.exe"

/netonly フラグを使用すると、ローカルの資格情報で exe を実行し、リモートの資格情報でネットワークにアクセスできるようになりました。とにかく、リモート サーバーから期待どおりの結果セットを取得したと思います。問題は、runas コマンドによってアプリケーションのデバッグが非常に難しくなり、いい匂いがしないことでした。

最終的に、Active Directory を操作するための認証について話しているコード プロジェクトに関するこの記事を見つけました。偽装を行うメイン クラスは次のとおりです。

    システムを使用する;
    System.Runtime.InteropServices を使用します。// DllImport
    System.Security.Principal の使用; // WindowsImpersonationContext

    名前空間 TestApp
    {
        クラスの偽装者
        {
            // グループ型の列挙型
            enum SECURITY_IMPERSONATION_LEVEL : int
            {
                セキュリティ匿名 = 0、
                セキュリティ識別 = 1、
                セキュリティ偽装 = 2,
                SecurityDelegation = 3
            }

            // ユーザートークンを取得
            [DllImport("advapi32.dll", SetLastError = true)]
            static extern bool LogonUser(文字列 pszUsername、文字列 pszDomain、文字列 pszPassword、
                int dwLogonType、int dwLogonProvider、ref IntPtr phToken);

            // LogonUser から返された開いている手を閉じます
            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
            extern static bool CloseHandle(IntPtr ハ​​ンドル);

            // 重複するトークン ハンドルを作成します
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
                int SECURITY_IMPERSONATION_LEVEL、ref IntPtr DuplicateTokenHandle);

            WindowsImpersonationContext newUser;

            ///
            /// ユーザーになりすます試み。成功した場合はリターン
            /// 新しいユーザー ID の WindowsImpersonationContext。
            ///
            /// なりすましたいユーザー名
            /// ログオン ドメイン
            /// ログオンに使用するユーザーのパスワード
            ///
            public Impersonator (文字列 sUsername、文字列 sDomain、文字列 sPassword)
            {
                // トークンを初期化
                IntPtr pExistingTokenHandle = 新しい IntPtr(0);
                IntPtr pDuplicateTokenHandle = 新しい IntPtr(0);
                pExistingTokenHandle = IntPtr.Zero;
                pDuplicateTokenHandle = IntPtr.Zero;

                // ドメイン名が空白の場合、ローカル マシンと見なす
                if (sDomain == "")
                    sDomain = System.Environment.MachineName;

                試す
                {
                    const int LOGON32_PROVIDER_DEFAULT = 0;

                    // トークンを作成
                    // const int LOGON32_LOGON_INTERACTIVE = 2;
                    const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
                    //const int SecurityImpersonation = 2;

                    // トークンへのハンドルを取得
                    bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                        LOGON32_LOGON_NEW_CREDENTIALS、LOGON32_PROVIDER_DEFAULT、ref pExistingTokenHandle);

                    // 偽装は失敗しましたか?
                    if (false == bImpersonated)
                    {
                        int nErrorCode = Marshal.GetLastWin32Error();

                        // LogonUser が失敗した理由を表示します
                        throw new ApplicationException("LogonUser() failed with error code: " + nErrorCode);
                    }

                    bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);

                    // DuplicateToken は失敗しましたか?
                    if (false == bRetVal)
                    {
                        int nErrorCode = Marshal.GetLastWin32Error();
                        CloseHandle(pExistingTokenHandle); // 既存のハンドルを閉じる

                        // DuplicateToken が失敗した理由を表示します
                        throw new ApplicationException("DuplicateToken() はエラー コードで失敗しました: " + nErrorCode);
                    }
                    そうしないと
                    {
                        // 新しいプライマリ トークンを使用して新しい ID を作成します
                        WindowsIdentity newId = 新しい WindowsIdentity(pDuplicateTokenHandle);
                        WindowsImpersonationContext impersonatedUser = newId.Impersonate();

                        newUser = impersonatedUser;
                    }
                }
                最後に
                {
                    // ハンドルを閉じる
                    if (pExistingTokenHandle != IntPtr.Zero)
                        CloseHandle(pExistingTokenHandle);
                    if (pDuplicateTokenHandle != IntPtr.Zero)
                        CloseHandle(pDuplicateTokenHandle);
                }
            }

            public void 元に戻す()
            {
                newUser.Undo();
            }
        }
    }

それを使用するには:

Impersonator impersonator = new Impersonator("username", "domain", "password");

//Connect to and use SQL server

impersonator.Undo();

Undo メソッドを追加しました。そうしないと、偽装オブジェクトがガベージ コレクションされる傾向がありました。また、LOGON32_LOGON_NEW_CREDENTIALS を使用するようにコードを変更しましたが、これは機能させるために突っ込んで実行するものでした。runas の /netonly フラグと同じような気がします。また、コンストラクターを少し分解します。

于 2011-01-19T14:39:59.273 に答える
4

接続文字列でユーザー名とパスワードを指定しても意味がありません。これらは SQL 認証を暗示しており、SQL Server が Windows 認証のみを受け入れることを既に指定しているためです。

サーバーが SQL 認証を許可していない場合、接続する唯一の方法は Windows 認証を使用することです。IntegratedSecurity=true. つまり、クライアントは、プロセスを実行している (または現在偽装されている) 資格情報として認証されます。

Windows 認証が機能するには、次のいずれかを選択する必要があります。

  • ドメインに参加していないマシンを、サーバー ドメインを信頼するドメイン (独自のドメインにすることもできます) に参加させ、クライアント プロセスを domain\user 資格情報として実行します。
  • NTLM ミラーリング アカウントを使用します。クライアントとサーバーのローカル ユーザーのペアで、同じ名前とパスワードを使用します。
  • SQL Server への ANONYMOUS アクセスを許可します。

クライアント ホストにサーバー ドメインを信頼させることも、NTLM ミラーリング アカウントを追加することもできず、SQL Server 管理者が ANONYMOUS を有効にしないほど正気である場合は、接続できません。

于 2010-05-12T20:34:02.980 に答える
2

As you correctly say, JDBC or Perl on a Linux machine can both connect to an SQL Server using Windows authentication and credentials which differ from the currently logged on user. The same is true for Windows CE devices, by the way.

I think that this is that this is not an issue of C# but of the SQL Server OLE DB driver. I guess the methods mentioned above "pretend to be a Windows machine using some specific credentials" on the network level; a feature, which the SQL Server OLE DB driver lacks. Thus, my suggestion would be to look for an alternative (maybe commercial?) OLE DB driver that can access SQL Server databases. I'm not sure if such a thing exists, though.

于 2010-08-22T07:47:28.270 に答える
2

SQL Server 認証、つまりユーザー名とパスワードを使用した認証を許可するようにSQL Serverを構成する必要があります。

サーバー認証のようなドメイン ユーザー名/パスワードによる認証はできません。つまり、ドメイン ユーザー名/パスワードを直接指定します。

もちろん、私が間違っている可能性もありますが、これは C# や .NET の問題ではないと確信しています。Perl または Java アプリケーションで SQL Server にログインするにはどうすればよいですか??

于 2010-05-12T20:22:33.463 に答える
0

jTDS JDBC ドライバーを使用して非ドメイン マシンから接続するために使用するサンプル コードを次に示します。

Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance(); 文字列 url = "jdbc:jtds:sqlserver://server/database;domain=domain"; conn = DriverManager.getConnection(url, "ユーザー", "パスワード");

于 2010-05-12T22:23:15.827 に答える
0

私がよりよく知っている Java の回答を提供します。上記の 4 つのパラメーターで jTDS JDBC ドライバーを使用します。私があまり知らないPerlアプリケーションですが、Linuxボックスで実行されており、同じパラメーターで接続できます。SQL 認証をサポートするように SQL Server を変更できません。

Remus の提案に答えるには、彼が提案する 3 つのことのいずれも実行できませんが、Java および Perl アプリケーションは接続できます。他のアイデアはありますか?

ありがとう、マーティン

于 2010-05-12T20:52:52.903 に答える
0

資格情報を求めるオプションはありますか?

于 2010-05-12T21:11:17.697 に答える