Для меня 'webClient.UseDefaultCredentials = true;' решает его только на локальном, а не в веб-приложении на сервере, подключенном к другому серверу. Я не мог добавить необходимые учетные данные в Windows как пользователь, но позже я нашел какой-то способ программирования - я не буду проверять его, поскольку уже создал собственное решение. А также я не хочу манипулировать с реестром веб-сервера , даже если у меня есть необходимые права администратора. Все эти проблемы связаны с внутренней обработкой Windows аутентификации NTLM («Домен Windows») и всеми библиотеками и инфраструктурами, построенными на этом (например, .NET).
Таким образом, для меня решение было довольно простым - создать прокси-приложение в многоплатформенной технологии с многоплатформенной библиотекой NTLM, в которой связь NTLM создается вручную в соответствии с общедоступными спецификациями, а не путем запуска встроенного кода Окна. Я сам выбрал Node.js и библиотеку httpntlm , потому что она содержит только один единственный исходный файл с несколькими строками и вызывает его из .NET как программу, возвращающую загруженный файл (также я предпочитаю передавать ее через стандартный вывод вместо создания временного файла).
Программа Node.js в качестве прокси для загрузки файла за аутентификацией NTLM:
var httpntlm = require('httpntlm'); // https://github.com/SamDecrock/node-http-ntlm
//var fs = require('fs');
var login = 'User';
var password = 'Password';
var domain = 'Domain';
var file = process.argv.slice(2); // file to download as a parameter
httpntlm.get({
url: 'https://server/folder/proxypage.aspx?filename=' + file,
username: login,
password: password,
workstation: '',
domain: domain,
binary: true // don't forget for binary files
}, function (err, res/*ponse*/) {
if (err) {
console.log(err);
} else {
if (res.headers.location) { // in my case, the server redirects to a similar URL,
httpntlm.get({ // now containing the session ID
url: 'https://server' + res.headers.location,
username: login,
password: password,
workstation: '',
domain: domain,
binary: true // don't forget for binary files
}, function (err, res) {
if (err) {
console.log(err);
} else {
//console.log(res.headers);
/*fs.writeFile("434980.png", res.body, function (err) { // test write
if (err) // to binary file
return console.log("Error writing file");
console.log("434980.png saved");
});*/
console.log(res.body.toString('base64')); // didn't find a way to output
} // binary file, toString('binary')
}); // is not enough (docs say it's
// just 'latin1')...
} else { // if there's no redirect
//console.log(res.headers); // ...so I output base64 and
console.log(res.body.toString('base64')); // convert it back in the caller
} // code
}
});
Код вызывающего абонента .NET (веб-приложение, загружающее файлы из веб-приложения на другой сервер)
public static string ReadAllText(string path)
{
if (path.StartsWith("http"))
return System.Text.Encoding.Default.GetString(ReadAllBytes(path));
else
return System.IO.File.ReadAllText(path);
}
public static byte[] ReadAllBytes(string path)
{
if (path.StartsWith("http"))
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "node.exe"; // Node.js installs into the PATH
psi.Arguments = "MyProxyDownladProgram.js " +
path.Replace("the base URL before the file name", "");
psi.WorkingDirectory = "C:\\Folder\\With My\\Proxy Download Program";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
Process p = Process.Start(psi);
byte[] output;
try
{
byte[] buffer = new byte[65536];
using (var ms = new MemoryStream())
{
while (true)
{
int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
break;
ms.Write(buffer, 0, read);
}
output = ms.ToArray();
}
p.StandardOutput.Close();
p.WaitForExit(60 * 60 * 1000); // wait up to 60 minutes
if (p.ExitCode != 0)
throw new Exception("Exit code: " + p.ExitCode);
}
finally
{
p.Close();
p.Dispose();
}
// convert the outputted base64-encoded string to binary data
return System.Convert.FromBase64String(System.Text.Encoding.Default.GetString(output));
}
else
{
return System.IO.File.ReadAllBytes(path);
}
}