C# asp.net模拟如何与System.Threading.Task一起工作?

C# asp.net模拟如何与System.Threading.Task一起工作?,c#,asp.net,iis,impersonation,C#,Asp.net,Iis,Impersonation,我想使用客户端用户的凭据访问数据库 我的代码: 我在system.web节点中具有带模拟属性的标识标记: 我在system.webServer节点中有验证标记: 我已将身份验证设置为windows: 我已将应用程序设置为使用passthrough: 我重新启动了iis。 我不知道这是怎么回事,或者我完全误解了它。根据您的评论,您似乎在任务中运行System.Security.Principal.WindowsIdentity.GetCurrent().Name,并获取应用程序池的标识

我想使用客户端用户的凭据访问数据库

我的代码: 我在system.web节点中具有带模拟属性的标识标记:

我在system.webServer节点中有验证标记:

我已将身份验证设置为windows:

我已将应用程序设置为使用passthrough:

我重新启动了iis。
我不知道这是怎么回事,或者我完全误解了它。

根据您的评论,您似乎在任务中运行
System.Security.Principal.WindowsIdentity.GetCurrent().Name
,并获取应用程序池的标识,而不是模拟用户的标识。这是一个常见的问题(请看)

然而,有一个解决办法。如果仍希望任务以模拟用户的身份运行,则必须在任务运行之前保存当前用户的令牌,并尝试按如下方式“重新模拟”任务的上下文:

IntPtr currentUser = WindowsIdentity.GetCurrent().Token; // This token points to the impersonated user

Task.Run(() => 
{
    using (WindowsIdentity.Impersonate(token))
    {
        // Connect to DB.
    }
}
这确保了
Using
块中的任何内容都以模拟用户的身份运行。

有这样一个问题:

Windows互操作

public static class Win32LogonInterop
{
    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static WindowsIdentity LogOn(string domain, string userName, string password)
    {
        IntPtr token = IntPtr.Zero;

        if (NativeMethods.LogonUser(userName, domain, password, ConnectionKind.NewCredentials, Provider.Default, out token))
        {
            return new WindowsIdentity(token);
        }
        else
        {
            RaiseError();
            return null;
        }
    }

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static void LogOff(WindowsIdentity identity)
    {
        if (identity != null)
        {
            if (!NativeMethods.CloseHandle(identity.Token))
                RaiseError();
        }
    }

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    private static void RaiseError()
    {
        int errorCode = Marshal.GetLastWin32Error();
        throw new Win32Exception(errorCode);
    }
}

internal static class NativeMethods
{
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool LogonUser(
            string userName,
            string domain,
            string password,
            ConnectionKind connectionKind,
            Provider provider,
        out IntPtr token);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CloseHandle(IntPtr handle);
}

public enum Provider
{
    Default = 0,
    WindowsNT35 = 1,
    WindowsNT40 = 2,
    WindowsNT50 = 3
}

public enum SecurityLevel
{
    Anonymous = 0,
    Identification = 1,
    Impersonation = 2,
    Delegation = 3
}

public enum ConnectionKind
{
    Unknown = 0,
    Interactive = 2,
    Network = 3,
    Batch = 4,
    Service = 5,
    Unlock = 7,
    NetworkClearText = 8,
    NewCredentials = 9
}
模拟方法

private void MyMethod(string domain, string userName, string password)
{
    WindowsIdentity _identity = Win32LogonInterop.LogOn(domain, userName, password);
    WindowsImpersonationContext impersonation = null;
    try
    {
        impersonation = _identity.Impersonate();

        // Stuff that needs impersonation
    }
    finally
    {
        if (impersonation != null)
        {
            impersonation.Undo();
            impersonation.Dispose();
        }
        if (_identity != null)
        {
            Win32LogonInterop.LogOff(_identity);
        }
    }
}

示例连接字符串也可以澄清您实际尝试连接的内容。。。我怀疑您有比“asp.net模拟如何工作”更具体的问题(因为它太宽泛了),但还不清楚问题是什么。谢谢Daniel,但这并没有解释如何执行代码,因为模拟用户是您的数据库,而不是IIS?如果是这样,您需要做一些工作来设置两台服务器之间的可信身份验证。@ChrisHayes请关闭问题或自行回答(您可能仍然希望更新问题,使其至少具有更好的标题)。
<authentication mode="Windows" />
IntPtr currentUser = WindowsIdentity.GetCurrent().Token; // This token points to the impersonated user

Task.Run(() => 
{
    using (WindowsIdentity.Impersonate(token))
    {
        // Connect to DB.
    }
}
public static class Win32LogonInterop
{
    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static WindowsIdentity LogOn(string domain, string userName, string password)
    {
        IntPtr token = IntPtr.Zero;

        if (NativeMethods.LogonUser(userName, domain, password, ConnectionKind.NewCredentials, Provider.Default, out token))
        {
            return new WindowsIdentity(token);
        }
        else
        {
            RaiseError();
            return null;
        }
    }

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static void LogOff(WindowsIdentity identity)
    {
        if (identity != null)
        {
            if (!NativeMethods.CloseHandle(identity.Token))
                RaiseError();
        }
    }

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    private static void RaiseError()
    {
        int errorCode = Marshal.GetLastWin32Error();
        throw new Win32Exception(errorCode);
    }
}

internal static class NativeMethods
{
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool LogonUser(
            string userName,
            string domain,
            string password,
            ConnectionKind connectionKind,
            Provider provider,
        out IntPtr token);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CloseHandle(IntPtr handle);
}

public enum Provider
{
    Default = 0,
    WindowsNT35 = 1,
    WindowsNT40 = 2,
    WindowsNT50 = 3
}

public enum SecurityLevel
{
    Anonymous = 0,
    Identification = 1,
    Impersonation = 2,
    Delegation = 3
}

public enum ConnectionKind
{
    Unknown = 0,
    Interactive = 2,
    Network = 3,
    Batch = 4,
    Service = 5,
    Unlock = 7,
    NetworkClearText = 8,
    NewCredentials = 9
}
private void MyMethod(string domain, string userName, string password)
{
    WindowsIdentity _identity = Win32LogonInterop.LogOn(domain, userName, password);
    WindowsImpersonationContext impersonation = null;
    try
    {
        impersonation = _identity.Impersonate();

        // Stuff that needs impersonation
    }
    finally
    {
        if (impersonation != null)
        {
            impersonation.Undo();
            impersonation.Dispose();
        }
        if (_identity != null)
        {
            Win32LogonInterop.LogOff(_identity);
        }
    }
}