Pour moi, 'webClient.UseDefaultCredentials = true;' ne résout le problème que localement, pas dans l'application web sur le serveur se connectant à un autre serveur. Je n'ai pas pu ajouter les informations d'identification nécessaires dans Windows en tant qu'utilisateur, mais j'ai ensuite trouvé une méthode de programmation - je ne la testerai pas car j'ai déjà trouvé ma propre solution. De plus, je ne veux pas manipuler le registre du serveur Web, même si j'ai les droits d'administrateur nécessaires. Tous ces problèmes sont dus à la gestion interne de Windows de l'authentification NTLM ("Domaine Windows") et de toutes les bibliothèques et frameworks construits par-dessus (par exemple .NET).
La solution pour moi était assez simple en théorie - créer une application proxy dans une technologie multiplateforme avec une bibliothèque NTLM multiplateforme où la communication NTLM est créée à la main selon les spécifications publiques, et non en exécutant le code intégré dans Windows. J'ai choisi Node.js et la bibliothèque httpntlm, car il s'agit d'un seul fichier source avec quelques lignes et l'appeler depuis .NET en tant que programme renvoyant le fichier téléchargé (je préfère également le transférer via la sortie standard au lieu de créer un fichier temporaire).
Programme Node.js en tant que proxy pour télécharger un fichier derrière l'authentification NTLM :
var httpntlm = require('httpntlm'); // https://github.com/SamDecrock/node-http-ntlm
//var fs = require('fs');
var login = 'Utilisateur';
var password = 'Mot de passe';
var domain = 'Domaine';
var file = process.argv.slice(2); // fichier à télécharger en tant que paramètre
httpntlm.get({
url: 'https://server/dossier/pageproxy.aspx?nomfichier=' + file,
username: login,
password: password,
workstation: '',
domain: domain,
binary: true // n'oubliez pas pour les fichiers binaires
}, function (err, res/*ponse*/) {
if (err) {
console.log(err);
} else {
if (res.headers.location) { // dans mon cas, le serveur redirige vers une URL similaire,
httpntlm.get({ // maintenant contenant l'ID de session
url: 'https://serveur' + res.headers.location,
username: login,
password: password,
workstation: '',
domain: domain,
binary: true // n'oubliez pas pour les fichiers binaires
}, 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) // au fichier binaire
return console.log("Erreur d'écriture du fichier");
console.log("434980.png enregistré");
});*/
console.log(res.body.toString('base64')); // je n'ai pas trouvé de moyen de sortir
} // un fichier binaire, toString('binary')
}); // n'est pas suffisant (la doc dit que c'est
// juste 'latin1')...
} else { // s'il n'y a pas de redirection
//console.log(res.headers); // ...alors je sors en base64 et
console.log(res.body.toString('base64')); // le convertir à nouveau dans le code appelant
} // code
}
});
Code appelant .NET (l'application Web téléchargeant des fichiers à partir d'une autre application Web sur un autre serveur) :
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 s'installe dans le PATH
psi.Arguments = "MyProxyDownladProgram.js " +
path.Replace("l'URL de base avant le nom du fichier", "");
psi.WorkingDirectory = "C:\\Dossier\\Avec Mon\\Programme de Téléchargement Proxy";
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); // attendre jusqu'à 60 minutes
if (p.ExitCode != 0)
throw new Exception("Code de sortie : " + p.ExitCode);
}
finally
{
p.Close();
p.Dispose();
}
// convertir la chaîne base64 encodée en sortie en données binaires
return System.Convert.FromBase64String(System.Text.Encoding.Default.GetString(output));
}
else
{
return System.IO.File.ReadAllBytes(path);
}
}