【问题标题】:ASP.NET impersonation from code (C#) and connected SQL Server Express user来自代码 (C#) 的 ASP.NET 模拟和连接的 SQL Server Express 用户
【发布时间】:2015-01-23 11:43:33
【问题描述】:

我在使用代码 (C#) 模拟 ASP.NET 和使用 SQL Server Express 时遇到问题:

我能够成功模拟并连接到 SQL Server,但是执行 SELECT CURRENT_USER 返回 guest 而不是 TestUser_001

注意:我尝试使用LOGON32_LOGON_NETWORK_CLEARTEXT 进行模拟,然后在调用LogonUser 时使用LOGON32_LOGON_INTERACTIVE - 结果保持不变。我正在执行此模拟代码的帐户设置了Act as part of the operating system。在 IIS Express(Visual Studio 2013 中的 F5)下测试。我从未以TestUser_001 的身份交互登录并连接到SQL Server Express 实例——Security\Logins 下没有MY_DOMAIN\TestUser_001——希望在使用代码时自动发生这种情况。

using (var impersonation = new ImpersonationHelper("TestUser_001", "MY_DOMAIN", "pass"))
{
    using (var conn = new SqlConnection(@"Data Source=MY_DOMAIN\SQLEXPRESS;Integrated Security=True;"))
    {
        conn.Open();

        using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = "SELECT CURRENT_USER";
            var result = cmd.ExecuteScalar();
        }
    }
}

这是基本的ImpersonationHelper 实现:

public class ImpersonationHelper : IDisposable
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    [DllImport("advapi32.dll")]
    public static extern int LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken
    );

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(
        IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken
    );

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);

    private readonly WindowsImpersonationContext impersonationContext_;

    public ImpersonationHelper(string username, string domain, string password)
    {
        var token = IntPtr.Zero;
        var token_duplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref token_duplicate) != 0)
                {
                    var temp_windows_identity = new WindowsIdentity(token_duplicate);
                    impersonationContext_ = temp_windows_identity.Impersonate();

                    if (impersonationContext_ != null)
                    {
                        CloseHandle(token);
                        CloseHandle(token_duplicate);
                        return;
                    }
                }
            }
        }

        if (token != IntPtr.Zero)
            CloseHandle(token);

        if (token_duplicate != IntPtr.Zero)
            CloseHandle(token_duplicate);

        throw new Exception(string.Format("Unable to impersonate as {0}\\{1}.", username, domain));
    }

    public void Dispose()
    {
        impersonationContext_.Undo();
    }
}

【问题讨论】:

  • 什么是 ImpersonationHelper?构造函数是否已经执行了模拟,还是需要先调用某个方法?
  • ImpersonationHelper 已经进行了模拟。 WindowsIdentity.GetCurrent().NameImpersonationHelper 之后调用,在连接到 SQL Express 之前返回 My_DOMAIN\TestUser_001
  • SELECT SUSER_SNAME(); 返回什么?
  • SELECT SUSER_SNAME(); 确实返回 MY_DOMAIN\TestUser_001,但用户登录名未列在 Security\Logins 下。

标签: c# asp.net sql-server sql-server-express impersonation


【解决方案1】:

感谢Dan Guzman - SQL Server MVP 和所有其他帮助解决这个问题的人。我想我会将此标记为答案,因为模拟有效并且 SQL Server 报告了正确的用户。

【讨论】:

    猜你喜欢
    • 2010-09-27
    • 2012-10-12
    • 2011-07-02
    • 1970-01-01
    • 2014-02-23
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    相关资源
    最近更新 更多