问题 我可以模拟使用表单身份验证进行身份验证的客户端并建立与SQL Server的可信连接吗?


这是我一直在努力做的事情

使用表单身份验证和活动目录成员身份构建ASP.NET MVC 3应用程序。 Web服务器和数据库是不同的物理服务器,因此是双跃点。

我认为答案就是这篇较旧的文章 约束委派和协议转换?到目前为止,我还没有能够使用该技术。

在生产设置中部署到Windows 2008(IIS7)之前,我正在从我的DEV机器(Windows 7,IIS7)中为Web服务器测试这个。 Windows 2008会有所作为吗?

什么有效,什么失败

我可以使用表单身份验证和AD成员身份登录。这似乎工作得很好。当我尝试使用此代码进行数据库调用时:

public void AsUser(Action action)
    {
        using (var id = new WindowsIdentity(User.Identity.Name + @"@example.com"))
        {
            WindowsImpersonationContext context = null;
            try
            {
                context = id.Impersonate();
                action.Invoke();
            }
            catch (Exception ex)
            {
                // ex.Message is The type initializer for System.Data.SqlClient.SqlConnection threw an exception
                // buried inner exeption is Requested registry access is not allowed
            }
            finally
            {
                if (context != null)
                {
                    context.Undo();
                }
            }
        }
    }

它失败了,导致我认为我在本地DEV服务器上设置了问题。内在的例外是 Requested registry access is not allowed

如果我设置断点并检查 WindowsIdentity 之后 Impersonate() 打电话我看到了 ImpersonationLevel 被设定为 Identification。这似乎是一个线索,它没有正确设置。谁能确认一下?

我是否在正确的轨道上,甚至可以设置?  任何指针将不胜感激。


5917
2018-02-09 16:12


起源



答案:


我认为你走在正确的轨道上。您只需要在协议转换设置上进行更多故障排除工作。

我假设您正确配置了Active Directory成员资格提供程序,以便您可以使用Active Directory用户名和密码成功登录Web页面。如果不是这样,请忽略我的其余答案:)

从我在您的问题中看到的,您使用WindowsIdentity的S4USelf获得了用户的令牌。然后,您正在使用S4UProxy将模拟的令牌传递给SQL Server。既然你说过了 ImpersonationLevel.Identification 只是,这意味着你没有进行协议转换。

您需要了解允许一台计算机在域中执行协议转换是非常高的权限。授予服务器进行协议转换几乎意味着您相信该服务器几乎就像一个域控制器。您需要在AD中有意识地做出这个决定,以使服务器具备此功能,并且您必须成为多米尼加管理员才能进行此更改。如果你还没有这样做,你可能没有正确设置你的东西。

有几件事需要检查。

首先,确保选择“信任此计算机以仅委派给指定的服务”,然后在服务帐户上选择“选择使用任何身份验证协议”。您可能想要创建域帐户。 这里 是一个如何为ASP.NET创建服务帐户的链接。请记住,您需要一个域帐户。创建域服务帐户后,请确保转到该帐户的委派选项卡并选择正确的选项。

其次,您需要确保正确设置SPN。我意识到您发布的链接仅提及ASP.NET服务帐户的SPN。实际上,您还需要确保SQL服务器上的服务帐户也正确设置。另外,Windows根本不会使用Kerberos身份验证。它将回归使用NTLM。在SQL Server上正确设置SPN有很多细节。你可以查一下 这里 首先,看看你有没有运气。根据我的经验,大多数DBA都不知道如何正确设置它们。他们甚至都没有意识到这一点,因为大多数应用程序都可以正常使用NTLM。您需要注意SQL服务器服务帐户及其使用的端口号。

第三,您需要确保没有任何禁用Kerberos委派的内容。默认情况下,某些敏感的AD帐户不允许委派。例如,内置管理员帐户。因此,您最好使用其他一些普通用户帐户进行测试。

UPDATE

我刚发现 另一篇文章 教你如何设置ASP.NET的协议转换。它提到您需要向TC服务帐户授予TCB权限,以确保它可以创建一个 Impersonation 键入WindowsIdentity。你可以试一试。


5
2018-02-22 07:06



谢谢你的所有信息。很多对我来说都是新的。我没有时间重置所有内容并从这些新知识开始,但我更有信心我现在可以开始工作了。 - Aaron Wagner
这种情况很糟糕......有13分钟直到赏金开始我选择了你的答案没有意识到这与“奖励”赏金不同。你有一半应该拥有的东西。对不起,我不理解系统,或者我错过了UI中的线索 - 无论哪种方式都是坏事。 - Aaron Wagner
@Aaron不用担心。谢谢你接受我的回答。在协议转换工作之后,实际上会遇到一些更常见的kerberos问题。例如。如果同一AD林中存在重复的SPN,则Kerberos身份验证将停止静默运行。要写出这类问题的完整答案是非常困难的。如果可以,MSDN将不需要有多篇文章和KB来解决类似的问题。如果您遇到其他一些AD问题,请使用标记问题 active-directory。您可能会获得更多有用的提示 - Harvey Kwok


答案:


我认为你走在正确的轨道上。您只需要在协议转换设置上进行更多故障排除工作。

我假设您正确配置了Active Directory成员资格提供程序,以便您可以使用Active Directory用户名和密码成功登录Web页面。如果不是这样,请忽略我的其余答案:)

从我在您的问题中看到的,您使用WindowsIdentity的S4USelf获得了用户的令牌。然后,您正在使用S4UProxy将模拟的令牌传递给SQL Server。既然你说过了 ImpersonationLevel.Identification 只是,这意味着你没有进行协议转换。

您需要了解允许一台计算机在域中执行协议转换是非常高的权限。授予服务器进行协议转换几乎意味着您相信该服务器几乎就像一个域控制器。您需要在AD中有意识地做出这个决定,以使服务器具备此功能,并且您必须成为多米尼加管理员才能进行此更改。如果你还没有这样做,你可能没有正确设置你的东西。

有几件事需要检查。

首先,确保选择“信任此计算机以仅委派给指定的服务”,然后在服务帐户上选择“选择使用任何身份验证协议”。您可能想要创建域帐户。 这里 是一个如何为ASP.NET创建服务帐户的链接。请记住,您需要一个域帐户。创建域服务帐户后,请确保转到该帐户的委派选项卡并选择正确的选项。

其次,您需要确保正确设置SPN。我意识到您发布的链接仅提及ASP.NET服务帐户的SPN。实际上,您还需要确保SQL服务器上的服务帐户也正确设置。另外,Windows根本不会使用Kerberos身份验证。它将回归使用NTLM。在SQL Server上正确设置SPN有很多细节。你可以查一下 这里 首先,看看你有没有运气。根据我的经验,大多数DBA都不知道如何正确设置它们。他们甚至都没有意识到这一点,因为大多数应用程序都可以正常使用NTLM。您需要注意SQL服务器服务帐户及其使用的端口号。

第三,您需要确保没有任何禁用Kerberos委派的内容。默认情况下,某些敏感的AD帐户不允许委派。例如,内置管理员帐户。因此,您最好使用其他一些普通用户帐户进行测试。

UPDATE

我刚发现 另一篇文章 教你如何设置ASP.NET的协议转换。它提到您需要向TC服务帐户授予TCB权限,以确保它可以创建一个 Impersonation 键入WindowsIdentity。你可以试一试。


5
2018-02-22 07:06



谢谢你的所有信息。很多对我来说都是新的。我没有时间重置所有内容并从这些新知识开始,但我更有信心我现在可以开始工作了。 - Aaron Wagner
这种情况很糟糕......有13分钟直到赏金开始我选择了你的答案没有意识到这与“奖励”赏金不同。你有一半应该拥有的东西。对不起,我不理解系统,或者我错过了UI中的线索 - 无论哪种方式都是坏事。 - Aaron Wagner
@Aaron不用担心。谢谢你接受我的回答。在协议转换工作之后,实际上会遇到一些更常见的kerberos问题。例如。如果同一AD林中存在重复的SPN,则Kerberos身份验证将停止静默运行。要写出这类问题的完整答案是非常困难的。如果可以,MSDN将不需要有多篇文章和KB来解决类似的问题。如果您遇到其他一些AD问题,请使用标记问题 active-directory。您可能会获得更多有用的提示 - Harvey Kwok


这是我使用的课程。此外,您还需要检查并查看运行AppPool的进程是否具有足够的权限进行模拟,因为它是一种特权活动。我会给用户帐户说明应用程序池在临时管理员权限下运行(当然只是开发框),看看它是否有效,这样你就会知道它是否是权限问题。

public class ImpersonationHelper : IDisposable
    {
        private const int LOGON32_LOGON_INTERACTIVE = 2;
        private const int LOGON32_PROVIDER_DEFAULT = 0;
        private WindowsImpersonationContext _impersonationContext;
        private string _userName;
        private string _domain;
        private string _password;

        [DllImport("advapi32.dll")]
        public static extern int LogonUserA(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);

        public ImpersonationHelper(string domain, string userName, string password)
        {
            _userName = userName;
            _domain = domain;
            _password = password;
        }

        public void Start()
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(_userName, _domain, _password, LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        _impersonationContext = tempWindowsIdentity.Impersonate();
                        if (_impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
        }

        #region IDisposable Members

        void IDisposable.Dispose()
        {
            if (_impersonationContext != null)
            {
                _impersonationContext.Undo();
            }
        }

        #endregion
    }

2
2018-02-21 21:59



谢谢你的代码。我希望在没有外线电话的情况下留在幸福的管理土地上,但如果谈到这一点,我会试一试。 - Aaron Wagner


您是否在Windows 7或Windows 2008计算机上启用了模拟?本文介绍了如何设置它。 http://technet.microsoft.com/en-us/library/cc730708(WS.10).aspx。另外,你运行32位还是64位?


1
2018-02-21 19:31



64位。这有关系吗? - Aaron Wagner
有时。在这种情况下,我怀疑它。但更多信息总是更好 - Spidy


您还应该咨询您的AD管理员,看看是否允许模拟。我公司的AD政策不允许冒充。


1
2018-02-21 19:49





我想你已经确定了问题,但没有人提到过。 “双跃点”问题不允许你这样做。这是不可能的。有很多人写过这样的文章 斯科特福赛思

当您对IIS进行身份验证时   服务器使用集成   身份验证,耗尽你的   第一次'跳'。 IIS尝试访问时   一个网络设备,那将是   不是双倍或第二跳   允许。 IIS无法依次传递   那些凭据到下一个网络   设备,否则开发人员或   管理员可以滥用你的   凭证并以这种方式使用它们   网站访问者没有预料到。

匿名不会发生这种情况   访问或冒充假冒   因为在那种情况下IIS负责   验证你,然后它使用一个   本地或网络的不同用户   访问。这意味着应用程序池   身份或匿名用户可以制作一个   网络呼叫作为第一跳。

我认为很明显,除第一次连接外,您无法再通过凭证。


1
2018-02-22 17:57