【发布时间】:2013-08-08 03:40:15
【问题描述】:
根据我对 Windows 上的用户模拟的阅读,应该正确使用 LOGON32_LOGON_NEW_CREDENTIALS 登录类型来模拟用户到数据库。使用 Matt Johnson 的漂亮模拟包装器(最初发布 here,然后完善 here),我尝试对此进行测试——这是我的整个程序,除了定义我的特定 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();
}
}
}
但这不起作用。输出报告来自nt_user_name 和SUSER_NAME() 的me(我的底层登录用户)。 (并且 SQL Profiler 报告的内容完全相同;代码中的查询只是查看 SQL Profiler 告诉我的一种便捷方式。)
如果我从LogonType.NewCredentials 更改为LogonType.Interactive(这些枚举具有您期望的值,如pinvoke.net 中定义的那样),那么它确实有效——上面的代码报告了正确的域和用户模拟。但这也意味着正在模拟当前会话,这是我不想要的——我只希望模拟数据库连接。
我以为我在上面发现了一个故障——Johnson 的模拟包装器将登录提供程序硬编码为 LOGON32_PROVIDER_DEFAULT,而 LogonUser API 明确指出只有 LOGON32_PROVIDER_WINNT50 支持 LOGON32_LOGON_NEW_CREDENTIALS 登录类型登录提供程序。所以我抓住了源代码并添加了一个参数以允许指定必要的登录提供程序......但这没有任何区别。
那么我错过了什么?
【问题讨论】:
-
从问题上退后一步:如果您要使用集成安全性登录数据库服务器实例,则根本不必依赖模拟;在这种情况下,1. 使用 SQL Server 登录将是更简单的选择。如果您使用集成安全,2. 只需允许目标用户登录(但尽可能限制他们在服务器和数据库上的权限);或者(甚至更好:)3. 只让服务访问数据库,让您的应用程序只访问服务,该服务执行自己的身份验证和授权。
-
感谢您的建议,@stakx;但是,在这种情况下,我没有进行这些架构更改的灵活性。此外,在我找出上述失败的原因之前,我可能永远无法再睡个好觉了:-)!
-
如果您使用 C 获取 LOGON32_LOGON_NEW_CREDENTIALS 令牌,然后使用该令牌启动一个单独的进程来代表您执行 SQL 工作,会发生什么情况? (新进程可能在 C# 中。)
标签: c# windows impersonation