【问题标题】:Copy files across UNC [closed]跨 UNC 复制文件 [关闭]
【发布时间】:2013-02-15 04:06:40
【问题描述】:

我有一个服务器 A,它托管一个应用程序来将文件写入它的硬盘驱动器。我有另外 2 台服务器 B 和 C。B 和 C 可以通过 A 上的 UNC 共享访问。

我希望将写入 A 上的硬盘驱动器的任何文件复制到与服务器 B 和 C 类似的目录结构下。我尝试使用 File.Copy,但这每次都会给我一个拒绝访问。我将如何设置安全性以使其正常工作?或者有没有办法冒充用户?

谢谢

【问题讨论】:

  • 可能重复:stackoverflow.com/questions/2702109/… 编辑:错误的问题被标记为重复,但它显示了如何模拟所有相同的答案。
  • 我不明白为什么这个问题被关闭为题外话。这是一个关于如何在访问 UNC 共享时使用网络凭据进行身份验证的完全有效的问题。我在下面提供了一个优雅的答案。

标签: c# copy unc


【解决方案1】:

如果您只是尝试访问需要凭据的网络共享,您可以执行以下操作:

  1. 调用 WinAPI LogonUser 以获取网络凭据令牌。
  2. 将令牌包装在 WindowsIdentity 对象中。
  3. 在 WindowsIdentity 上调用 Impersonate。
  4. 访问网络资源。
  5. 释放 WindowsImpersonationContext 和 WindowsIdentity。
  6. 调用 WinAPI CloseHandle。

我创建了一个实现这种行为的一次性类。

...

    using (new NetworkImpersonationContext("domain", "username", "password"))
    {
        // access network here
    }

...

public class NetworkImpersonationContext : IDisposable
{
    private readonly WindowsIdentity _identity;
    private readonly WindowsImpersonationContext _impersonationContext;
    private readonly IntPtr _token;
    private bool _disposed;

    public NetworkImpersonationContext(string domain, string userName, string password)
    {
        if (!LogonUser(userName, domain, password, 9, 0, out _token))
            throw new Win32Exception();
        _identity = new WindowsIdentity(_token);
        try
        {
            _impersonationContext = _identity.Impersonate();
        }
        catch
        {
            _identity.Dispose();
            throw;
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        GC.SuppressFinalize(this);
        Dispose(true);
    }

    #endregion

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr hHandle);

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;
        _disposed = true;

        if (disposing)
        {
            _impersonationContext.Dispose();
            _identity.Dispose();
        }

        if (!CloseHandle(_token))
            throw new Win32Exception();
    }

    ~NetworkImpersonationContext()
    {
        Dispose(false);
    }
}

【讨论】:

    【解决方案2】:

    我不会尝试在 C# 中解决这个问题。已经有许多文件复制产品,包括为 Windows Server 2003 及更高版本内置的DFS Replication

    【讨论】:

      【解决方案3】:

      我不会尝试对安全性进行编程来支持这一点。您最好的选择是使用 Windows 进行配置(假设您使用的是 Windows 服务器)。您必须确保服务器 B 和 C 已分配权限以允许服务器 A 写入 UNC 共享。

      此时,假设这是Windows,您可以为服务器B和C的机器名称分配权限,或者您可以将服务器B和C放入一个组,并在服务器A上为该组分配权限。

      【讨论】:

        猜你喜欢
        • 2012-05-01
        • 2011-04-30
        • 1970-01-01
        • 2013-02-21
        • 1970-01-01
        • 2012-12-16
        • 2013-04-30
        • 1970-01-01
        • 2013-05-14
        相关资源
        最近更新 更多