使用“WindowsIdentityImpersonateMethod”无法从服务器获取文件

时间:2017-01-03 13:40:41

标签: c# .net server

我知道有很多关于Impersonate的问题,但我找不到正确的答案或找到解决问题的方法。

我正在尝试从运行我的代码的WM上的服务器复制文件。 我已经使用了这个“WindowsIdentityImpersonateMethod”,它可以为大多数人提供良好的工作。

对于我来说,当我想在我的WM上模仿另一个用户时,工作正常。 但是对于在不同Domaine上的服务器上模拟用户,它不起作用。

using System;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;

namespace WindowsIdentityImpersonateMethodWithDelegate
{
  public enum LogonType
  {
    LOGON32_LOGON_INTERACTIVE = 2,
    LOGON32_LOGON_NETWORK = 3,
    LOGON32_LOGON_BATCH = 4,
    LOGON32_LOGON_SERVICE = 5,
    LOGON32_LOGON_UNLOCK = 7,
    LOGON32_LOGON_NETWORK_CLEARTEXT = 8, // Win2K or higher
    LOGON32_LOGON_NEW_CREDENTIALS = 9 // Win2K or higher
  };

  public enum LogonProvider
  {
    LOGON32_PROVIDER_DEFAULT = 0,
    LOGON32_PROVIDER_WINNT35 = 1,
    LOGON32_PROVIDER_WINNT40 = 2,
    LOGON32_PROVIDER_WINNT50 = 3
  };



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

    [DllImport("kernel32.dll")]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [SuppressUnmanagedCodeSecurity]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr handle);

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

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

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

    /// <summary>
    /// Impersonates the specified domain name.
    /// </summary>
    /// <param name="domainName">Name of the domain.</param>
    /// <param name="userName">Name of the user.</param>
    /// <param name="userPassword">The user password.</param>
    /// <param name="actionToExecute">The action to execute.</param>
    /// <exception cref="System.ComponentModel.Win32Exception"></exception>
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]

    public void Impersonate(string domainName, string userName, string userPassword, Action actionToExecute)
    {
      SafeTokenHandle safeTokenHandle;

      try
      {

        const int LOGON32_PROVIDER_DEFAULT = 0;
        //This parameter causes LogonUser to create a primary token.
        const int LOGON32_LOGON_INTERACTIVE = 2;

        // Call LogonUser to obtain a handle to an access token.

        bool returnValue = LogonUser(userName, domainName, userPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);  //returns false
        //bool returnValue1 = LogonUser(userName, domainName, userPassword, 9, 3, 
          //out safeTokenHandle); // return always true, even when userName ist wrong

        if (returnValue == false)
        {
          int ret = Marshal.GetLastWin32Error();
          throw new System.ComponentModel.Win32Exception(ret);
        }

        using (safeTokenHandle)
        {

          // Use the token handle returned by LogonUser.
          using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
          {
            using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
            {
              bool test = File.Exists(@"\\10.29.14.05\c$\test.xml");  //always false, file is acessible from start->run
              bool test5 = Directory.Exists(@"\\10.99.10.25\c$\"); //false
              bool test1 = File.Exists(@"C:\test.xml"); //false
              Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);  //always local user
              actionToExecute();
            }
          }

        }

      }
      catch (Exception ex)
      {
        throw;
      }
    }
  }
}

我的用户拥有所有权利,它就是这样的。

string domain = "10.29.14.05";
string user = @"testtest\user1";
string password = "password!";

正如您在代码中看到的,我使用了两种不同的Logntype和LogonProviders。

bool returnValue = LogonUser(userName, domainName, userPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);  //returns false

当我使用这一行时。  我得到一个例外 System.ComponnentModel-Win32Exception “用户名或密码不正确”

bool returnValue1 = LogonUser(userName, domainName, userPassword, 9, 3, out safeTokenHandle);

当我使用此行时,即使userName错误,LogonUser方法也始终返回TRUE。

此行始终是本地用户

Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);

三个测试变量总是返回false

bool test = File.Exists(@"\\10.29.14.05\c$\test.xml");  //always false, file is accessible from start->run
bool test5 = Directory.Exists(@"\\10.99.10.25\c$\"); //false
bool test1 = File.Exists(@"C:\test.xml"); //false

如何解决这个问题? 方向搜索或任何东西将来自帮助,谢谢。

0 个答案:

没有答案