ASP.NET用户模拟

3
我有一个ASP.NET MVC应用程序,它访问数据库以检索数据,并在提交表单时更新另一个数据库。两个数据库和IIS位于不同的服务器上,用户将远程访问此应用程序,但所有内容都在我们的局域网内。用户通过组获得对数据库的访问权限。
这意味着我需要使用用户凭据(浏览ASP.NET应用程序的人)来访问两个数据库,但我一直无法让其正常工作。以下是我一直在尝试的方法:
部署应用程序后,在远程打开它时,它可以打开,但访问数据库的方法返回“Login failed for domain/servername”。
  1. Enabled impersonation: "An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode."
  2. validateIntegratedModeConfiguration="false" - > DirectoryServicesCOMException (0x80072020): An operations error occurred.
  3. Disabled impersonation and tried to add code to impersonate only on the section of code i access the DB using:

    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
    

    which resulted in Login failed for NT AUTHORITY/ANONYMOUS LOGON

我的连接字符串是

    "Data Source=" + SERVER + ";Initial Catalog=" + DB + ";Integrated Security=True;Connection Timeout=30;Trusted_Connection=true"

注意:当在 Visual Studio 上进行调试并在我部署它的服务器上本地访问时应用程序可以完美运行(启用模拟用户)。此外,我们使用智能卡登录,我不能向用户要求凭据。由于我们服务器的安全模型,我不能代表用户使用另一个 ID。

如果用户是内网外的,你如何期望在不要求凭据的情况下模拟他们的 Windows 身份? - jamesSampica
所有内容都在我们的内部网络中,包括用户和所有服务器。感谢您的回复! - YuriW
我正在看“用户将远程访问此”。我在这里假设你的意思是在你的内部网络之外? - jamesSampica
1
远程意味着不在服务器本地。例如:纽约公司内部使用Intranet访问托管在休斯顿的应用程序,该应用程序使用其他地方的数据库,但也在Intranet内。 - YuriW
明白了。看起来你可能已经在web.config中同时设置了impersonate='true'validateIntregrateMode='false',是吗? - jamesSampica
4个回答

2
我怀疑你的Web应用没有对用户进行身份验证,否则你不会收到“Login failed for NT AUTHORITY/ANONYMOUS LOGON”的消息。
检查你的IIS网站设置,并确保禁用匿名身份验证。

2
你正在做/被要求做的事情通常是不被赞同的。当你在连接字符串中设置Integrated Security=True时,访问连接的SID/用户由应用程序池定义。这使得SQL连接池可以非常高效地工作。
当你尝试使用通过身份验证或模拟的集成安全性访问SQL服务器时,你基本上失去了连接池的所有价值(因为现在每个连接都必须使用用户凭据创建,并且不能在请求之间共享)。
通常,当我遇到这种情况时,我会创建一个用户,授予数据库访问权限,并将该用户与应用程序池一起使用。当用户在网站上进行身份验证(Windows或基本认证)时,我使用Active Directory服务或LDAP来验证用户是否有权访问应用程序。

我们使用了“透传”认证思路对应用程序进行建模,因为它可能每天只会被1或2个人使用来提交特定类型的请求,但即使在这种情况下,这种方法也似乎行不通。你提出的解决方案最终是我们要实现的,并且似乎是这种情况下最好的选择,尽管我们将不得不修改服务器的安全模型。谢谢! - YuriW

0

我在MVC中遇到了类似的模拟问题。

我不得不使用win32调用编写出模拟登录特定用户的代码。然后我发现这与SQLClient不兼容,必须进一步改进。

这可能不完全符合您的要求,但这是我目前正在使用的代码,从各种互联网来源编译而来。

public class Impersonator
{
    public WindowsImpersonationContext Impersonate(string username, string domain, string password)
    {
        WindowsIdentity tempWindowsIdentity;
        const int LOGON32_PROVIDER_DEFAULT = 0;
        //This parameter causes LogonUser to create a primary token. 
        const int LOGON32_LOGON_INTERACTIVE = 2;
        SafeTokenHandle token;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (NativeMethods.RevertToSelf())
        {
            // Call LogonUser to obtain a handle to an access token. 
            bool returnValue = NativeMethods.LogonUser(
                username,
                domain,
                password,
                LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT,
                out token);

            if (returnValue)
            {
                if (NativeMethods.DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    NativeMethods.CloseHandle(tokenDuplicate);
                    return tempWindowsIdentity.Impersonate();
                }
                else
                {
                    throw new Exception("unable to login as specifed user - duplicate ");
                }
            }
            else
            {
                throw new Exception("unable to login as specifed user ");
            }
        }
        else
        {
            throw new Exception("could not revert to self ");
        }
        using (WindowsIdentity id = new WindowsIdentity(token.DangerousGetHandle()))
        {
            return id.Impersonate();
        }
    }
}
internal static class NativeMethods
{
    [DllImport("kernel32.dll")]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [SuppressUnmanagedCodeSecurity]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool LogonUser(
        String lpszUsername, 
        String lpszDomain, 
        String lpszPassword,
        int dwLogonType, 
        int dwLogonProvider, 
        out SafeTokenHandle phToken);

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

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

public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    private SafeTokenHandle()
        : base(true)
    {
    }

    protected override bool ReleaseHandle()
    {
        return NativeMethods.CloseHandle(handle);
    }
}

您的代码以用户名/域和密码作为参数,我们在公司内部网络使用智能卡登录。我不确定我是否能够适应这种穿透式智能卡身份验证场景... - YuriW
是的,我知道这对你的情况不完美。你需要获取用户的Windows标识符指针。我相信可以通过User.Identity实现。 - Ewan

0
造成这个问题的原因是服务器试图访问数据库,但数据库不信任该服务器,因此无法解析凭据。
您可以在应用程序池中使用显式 ID 并设置模拟禁用。IIS 将代表该 ID 运行。确保该 ID 具有数据库访问权限。这将是更安全的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接