Копирование файлов по сети через общий доступ к файлам, аутентификацию пользователя
Я создаю консольную программу .net С# для развертывания файла на сервере общих файлов Windows (папка, совместно используемая). Путь: \\192.168.0.76\htdocs\public
При запуске я получаю сообщение об ошибке:
[09:35:29]: [Step 1/3] Unhandled Exception: System.UnauthorizedAccessException: Access to the path '\\192.168.0.76\htdocs\public' is denied.
[09:35:29]: [Step 1/3] at DeployFileShare.Program.CopyDir(String source, String dest, String[] exclude, Boolean overwrite)
[09:35:29]: [Step 1/3] at DeployFileShare.Program.Deploy(String num, String source)
[09:35:29]: [Step 1/3] at DeployFileShare.Program.Main(String[] args)
[09:35:29]: [Step 1/3] Process exited with code -532459699
Думаю, мне нужно пройти аутентификацию. Я столкнулся с этим:
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsIdentity idnt = new WindowsIdentity(username, password);
WindowsImpersonationContext context = idnt.Impersonate();
Я также пробовал:
AppDomain.CreateDomain("192.168.0.76").SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsIdentity idnt = new WindowsIdentity("user", "pass");
WindowsImpersonationContext context = idnt.Impersonate();
Я не уверен, как его использовать. Когда я запускаю приложение, я получаю:
C:\Users\Administrator>DeployFileShare 1 R:\BuildOutput\_PublishedWebsites\Web 2
1
Deploy Started Web, version 21
-- Deploy Prepared
-- Deploying to 1
Unhandled Exception: System.Security.SecurityException: There are currently no l
ogon servers available to service the logon request.
at System.Security.Principal.WindowsIdentity.KerbS4ULogon(String upn)
at System.Security.Principal.WindowsIdentity..ctor(String sUserPrincipalName,
String type)
at DeployFileShare.Program.Authenticate(String server)
at DeployFileShare.Program.Deploy(String num, String source)
at DeployFileShare.Program.Main(String[] args)
The Zone of the assembly that failed was:
MyComputer
Вот базовый код:
static void Main()
{
Copy();
}
static void Copy()
{
AppDomain.CreateDomain(GetServerInfo(server, "server")).SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsIdentity idnt = new WindowsIdentity(GetServerInfo(server, "user"), GetServerInfo(server, "pass"));
WindowsImpersonationContext context = idnt.Impersonate();
string source = "C:\\someDir";
string dest = "\\192.168.0.76\shareFolder"
string[] sourceFiles = Directory.GetFiles(source, "*", SearchOption.AllDirectories);
foreach (string file in sourceFiles)
{
string local = file.Replace(source, "");
if (exclude.Contains(local))
continue;
if (!Directory.Exists(Path.GetDirectoryName(dest + "\\" + local)))
Directory.CreateDirectory(Path.GetDirectoryName(dest + "\\" + local));
File.Copy(file, dest + "\\" + local, overwrite);
Console.WriteLine("-- -- [copied] {0} -> {1}", file, dest + "\\" + local);
}
}
Система копирования кода в цикле for работает, я протестировал ее в своей локальной системе.
Если кто-нибудь знает, как я должен использовать WindowsIdentity и WindowsIdentity, чтобы заставить это работать, пожалуйста, просветите меня. Я смотрю вокруг, и документация на окнах не очень помогает.
В принципе, как я могу копировать в удаленный каталог, совместно используемый при входе в систему?
Ответы
Ответ 1
VB, но легко переводится на С#. Сделайте это перед вашей копией:
Private Sub Open_Remote_Connection(ByVal strComputer As String, ByVal strUserName As String, ByVal strPassword As String)
Dim ProcessStartInfo As New System.Diagnostics.ProcessStartInfo
ProcessStartInfo.FileName = "net"
ProcessStartInfo.Arguments = "use \\" & strComputer & "\c$ /USER:" & strUsername & " " & strPassword
ProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden
System.Diagnostics.Process.Start(ProcessStartInfo)
System.Threading.Thread.Sleep(2000)
End Sub
Ответ 2
Если вы хотите выполнить аутентификацию на удаленном компьютере, чтобы переместить файл, вы можете использовать функцию LogonUser и WindowsIdentity для выдачи себя за пользователя.
/// <summary>
/// Exécute une fonction en empruntant les credentials
/// </summary>
private T ApplyCredentials<T>(Func<T> func)
{
IntPtr token;
if (!LogonUser(
_credentials.UserName,
_credentials.Domain,
_credentials.Password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
out token))
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
try
{
// On doit être impersonifié seulement le temps d'ouvrir le handle.
using (var identity = new WindowsIdentity(token))
using (var context = identity.Impersonate())
{
return func();
}
}
finally
{
CloseHandle(token);
}
}
// ...
if (_credentials != null)
{
return this.ApplyCredentials(() => File.Open(path, mode, access, share));
}
return File.Open(path, mode, access, share);