從我對Windows用戶模擬的閱讀中,應該正確使用LOGON32_LOGON_NEW_CREDENTIALS登錄類型將用戶模擬爲數據庫。使用馬特約翰遜的好模擬包裝(最初發布here,然後打磨here),我試圖測試這一點 - 這是我的整個程序,除了常量定義我的特定DOMAIN,USER,PWD和CONN_STRING。使用LOGON32_LOGON_NEW_CREDENTIALS對Windows進行冒充有什麼魔力?
using System;
using System.Data.SqlClient;
using SimpleImpersonation;
namespace ImpersonationDemo
{
class Program
{
private static SqlConnection _connection;
static void Main(string[] args)
{
using (Impersonation.LogonUser(
DOMAIN, USER, PWD, LogonType.NewCredentials))
{
GetOpenConnection();
CheckDbCredentials();
CloseConnection();
}
Console.WriteLine("Press return to exit");
Console.ReadLine();
}
private static void CheckDbCredentials()
{
using (
var command = new SqlCommand(
"SELECT nt_user_name, SUSER_SNAME() "
+"FROM sys.dm_exec_sessions WHERE session_id = @@SPID",
_connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0}, {1}",
reader.GetString(0), reader.GetString(1));
}
}
}
}
private static void GetOpenConnection()
{
_connection = new SqlConnection(CONN_STRING);
_connection.Open();
}
private static void CloseConnection()
{
_connection.Close();
}
}
}
但這並不奏效。輸出報告me(我的基礎登錄用戶)來自nt_user_name
和SUSER_NAME()
。 (和SQL事件探查器報告完全一樣的東西;在代碼中的查詢僅僅是爲了看看SQL事件探查器告訴我一個便捷的方式。)
如果我改變從LogonType.NewCredentials
到LogonType.Interactive
(這些枚舉有你所期望的值,如定義在pinvoke.net),那麼它確實有效 - 上面的代碼報告了正確的DOMAIN和USER模擬。但這也意味着當前會話正在模擬,我不想 - 我只希望數據庫連接被模擬。
我以爲我找到了一個小故障在上面 - 約翰遜的假冒包裝硬編碼登錄提供商爲LOGON32_PROVIDER_DEFAULT
,當LogonUser API明確指出,LOGON32_LOGON_NEW_CREDENTIALS
登錄類型由LOGON32_PROVIDER_WINNT50
登錄提供僅支持。所以我抓住了源代碼並添加了一個參數來允許指定必要的登錄提供程序......但這沒有什麼區別。
那麼我錯過了什麼?
從這個問題退步:如果您要使用集成安全性登錄您的數據庫服務器實例,則根本不應該依賴模擬;在這種情況下,使用SQL Server登錄的** 1。**將是更容易的選項。如果您使用集成安全性,** 2。**只允許目標用戶登錄(但儘可能限制他們在服務器和數據庫上的權限);或者(甚至更好:) ** 3。**只允許服務訪問數據庫,並讓您的應用程序只訪問執行其自己的認證和授權的服務。 – stakx
我欣賞這些建議@stakx;但是,在這種情況下,我沒有靈活性來進行這些架構變更。而且,除非我發現上述失敗的原因,否則我可能永遠無法再次獲得健康的夜間睡眠:-)! –
如果您使用C獲取LOGON32_LOGON_NEW_CREDENTIALS標記,然後啓動一個包含標記的單獨流程來代表您執行SQL工作,會發生什麼情況? (新進程可以在C#中。) –