Переместить файл на сетевой ресурс (через олицетворение) C # - PullRequest
1 голос
/ 11 мая 2011

Я работал над проектом на C # (.net4).Project в значительной степени позволяет людям загружать файлы со своего локального компьютера в общий сетевой ресурс.

Общий сетевой ресурс защищен.Он доступен только пользователю с именем «proxy», который создается в активном каталоге.

Я провел некоторое исследование и обнаружил этот класс, который использовал для олицетворения.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Datacom.CorporateSys.Utilities
{
    public class ImpersonateUser
    {
        [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);

        WindowsImpersonationContext impersonationContext;

        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;
        private string p;
        private string p_2;
        private string p_3;


        private String UserName
        {
            set;
            get;
        }

        private String Domain
        {
            set;
            get;
        }

        private String Password
        {
            set;
            get;
        }

        /// <summary>
        /// Impersonates the user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="domain">The domain.</param>
        /// <param name="password">The password.</param>
        public ImpersonateUser(string userName, string domain, string password)
        {
            UserName = userName;
            Domain = domain;
            Password = password;
        }

        /// <summary>
        /// Impersonates the valid user.
        /// </summary>
        /// <returns></returns>
        public bool impersonateValidUser()
        {
            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);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        }

        /// <summary>
        /// Undoes the impersonation.
        /// </summary>
        public void undoImpersonation()
        {
            impersonationContext.Undo();
        }
    }
}

Примечание: сПамять Я думаю, что нашел это в качестве примера на MSDN.

Вот как я пытаюсь переместить файл с локального пути в сеть

 if (imp.impersonateValidUser())
                            {
                                System.IO.File.Copy(local_file, server_file, true);
                                imp.undoImpersonation();
                            }
                            else
                            {
                                throw new Exception("Unable to impersonate for uploading file.");
                            }

И это работает!У меня никогда не было проблем с подражанием - исключение никогда не бросалось.Он отлично работает и загружает файлы на сервер.Однако, когда я начал тестировать немного больше, я обнаружил, что если прокси-пользователь не вошел в систему на сервере (обычно я открываю вход в RDS и завершаю работу - не выходя из системы).

Я получаю другое исключение - исключение сетевого пути не найдено, и это происходит только тогда, когда я только что перезапустил сервер и «прокси» не вошел в систему.

Мой первыйМысль заключалась в том, что с классом олицетворения что-то не так, однако он отлично подражает, когда работает (т. е. файлы владеют прокси-пользователем).Тогда я подумал, что, возможно, «прокси» должен войти в систему, чтобы ОС могла использовать свои разрешения для фактического доступа к \ server \ uploads

.Обратите внимание: у меня нет контроля над сервером.Сервер win2k8 с установленным рабочим столом (иначе я не могу получить доступ к любым сетевым расположениям).

Спасибо!

1 Ответ

1 голос
/ 14 июня 2012

Предоставьте прокси-учетной записи право доступа «Вход в систему как пакетное задание» и используйте `LOGON32_LOGON_BATCH вместо интерактивного входа в систему.

...