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

时间:2011-02-09 16:12:49

标签: active-directory asp.net-mvc-3 forms-authentication trustedconnection

以下是我一直在尝试做的事情

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

我认为答案是关于constrained delegation and protocol transition的旧文章?到目前为止,我还没有能够使用该技术。

我在生产设置中部署到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。这似乎是一个线索,它没有正确设置。任何人都可以确认吗?

我是否在正确的轨道上,甚至可以设置?任何指针都将受到赞赏。

5 个答案:

答案 0 :(得分:5)

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

我假设您正确配置了Active Directory成员资格提供程序,以便您可以使用Active Directory用户名和密码成功登录网页。如果情况并非如此,请忽略我的其余答案:)

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

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

有几件事要检查。

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

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

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

<强>更新

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

答案 1 :(得分:2)

这是我使用的课程。此外,您还要检查并查看运行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 :(得分:1)

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

我认为你已经确定了问题,但没有人提到过。 “双跃点”问题不允许你这样做。这是不可能的。有很多人写过这篇文章,例如Scott Forsyth

  

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

     

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

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