6

根据我对 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_DEFAULTLogonUser API明确指出LOGON32_LOGON_NEW_CREDENTIALS只有登录提供程序支持登录类型时,Johnson 的模拟包装器将登录提供程序硬编码为LOGON32_PROVIDER_WINNT50。所以我抓住了源代码并添加了一个参数以允许指定必要的登录提供程序......但这没有任何区别。

那么我错过了什么?

4

1 回答 1

5

答案,我很惭愧地说,一直就在我面前。LogonUser API 状态:

此登录类型允许调用者克隆其当前令牌并为出站连接指定新凭据。新的登录会话具有相同的本地标识符,但对其他网络连接使用不同的凭据。[强调我的]

但是我的数据库与我正在运行的程序在同一台机器上,所以根据定义它不会显示新的凭据!我相信LOGON32_LOGON_NEW_CREDENTIALS一旦我将数据库移动到另一个盒子,模拟就会正常工作。叹。

于 2013-08-10T22:57:10.720 回答