根据我对 Windows 上的用户模拟的阅读,应该正确使用 LOGON32_LOGON_NEW_CREDENTIALS 登录类型来模拟用户到数据库。使用 Matt Johnson 的漂亮模拟包装器(最初发布在此处,然后在此处完善),我尝试对此进行测试——这是我的整个程序,除了定义我的特定 DOMAIN、USER、PWD 和 CONN_STRING 的常量。
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();
        }
    }
}
但这不起作用。输出从和报告我(我的底层登录用户)。(并且 SQL Profiler 报告的内容完全相同;代码中的查询只是查看 SQL Profiler 告诉我的一种便捷方式。)nt_user_nameSUSER_NAME()
如果我从LogonType.NewCredentialsto更改LogonType.Interactive(这些枚举具有您期望的值,如pinvoke.net上定义的那样),那么它确实有效——上面的代码报告了正确的 DOMAIN 和 USER 模拟。但这也意味着正在模拟当前会话,这是我不想要的——我只希望模拟数据库连接。
我想我在上面发现了一个小故障——LOGON32_PROVIDER_DEFAULT当LogonUser API明确指出LOGON32_LOGON_NEW_CREDENTIALS只有登录提供程序支持登录类型时,Johnson 的模拟包装器将登录提供程序硬编码为LOGON32_PROVIDER_WINNT50。所以我抓住了源代码并添加了一个参数以允许指定必要的登录提供程序......但这没有任何区别。
那么我错过了什么?