Nous avons rencontré une situation intéressante qui doit être résolue, et mes recherches se sont avérées nulles. J'appelle donc la communauté SO à l'aide.
Le problème est le suivant: nous avons besoin d'accéder par programme à un fichier partagé qui n'est pas dans notre domaine et qui ne se trouve pas dans un domaine externe de confiance via le partage de fichiers à distance / UNC. Naturellement, nous devons fournir des informations d'identification à la machine distante.
En règle générale, on résout ce problème de deux manières:
- Mappez le partage de fichiers en tant que lecteur et fournissez les informations d'identification à ce moment-là. Cela se fait généralement à l'aide de la
NET USE
commande ou des fonctions Win32 qui se dupliquentNET USE
. - Accédez au fichier avec un chemin UNC comme si l'ordinateur distant était sur le domaine et assurez-vous que le compte sous lequel le programme s'exécute est dupliqué (y compris le mot de passe) sur l'ordinateur distant en tant qu'utilisateur local. Exploitez essentiellement le fait que Windows fournira automatiquement les informations d'identification de l'utilisateur actuel lorsque l'utilisateur tente d'accéder à un fichier partagé.
- N'utilisez pas le partage de fichiers à distance. Utilisez FTP (ou un autre moyen) pour transférer le fichier, travaillez dessus localement, puis transférez-le à nouveau.
Pour des raisons diverses et diverses, nos architectes de sécurité / réseau ont rejeté les deux premières approches. La deuxième approche est évidemment une faille de sécurité; si l'ordinateur distant est compromis, l'ordinateur local est maintenant en danger. La première approche n'est pas satisfaisante car le lecteur nouvellement monté est une ressource partagée disponible pour d'autres programmes sur l'ordinateur local lors de l'accès aux fichiers par le programme. Même s'il est tout à fait possible de rendre cela temporaire, c'est toujours un trou à leur avis.
Ils sont ouverts à la troisième option, mais les administrateurs réseau distants insistent sur SFTP plutôt que sur FTPS, et FtpWebRequest ne prend en charge que FTPS. SFTP est l'option la plus compatible avec le pare-feu et il y a quelques bibliothèques que je pourrais utiliser pour cette approche, mais je préférerais réduire mes dépendances si je le peux.
J'ai recherché dans MSDN un moyen géré ou win32 d'utiliser le partage de fichiers à distance, mais je n'ai rien trouvé d'utile.
Et donc je demande: y a-t-il un autre moyen? Ai-je manqué une fonction win32 super secrète qui fait ce que je veux? Ou dois-je poursuivre une variante de l'option 3?
la source
Réponses:
La façon de résoudre votre problème consiste à utiliser une API Win32 appelée WNetUseConnection .
Utilisez cette fonction pour vous connecter à un chemin UNC avec authentification, PAS pour mapper un lecteur .
Cela vous permettra de vous connecter à une machine distante, même si elle n'est pas sur le même domaine, et même si elle a un nom d'utilisateur et un mot de passe différents.
Une fois que vous avez utilisé WNetUseConnection, vous pourrez accéder au fichier via un chemin UNC comme si vous étiez sur le même domaine. Le meilleur moyen est probablement d'utiliser les partages administratifs intégrés.
Exemple: \\ computername \ c $ \ program files \ Folder \ file.txt
Voici un exemple de code C # qui utilise WNetUseConnection.
Notez que pour NetResource, vous devez passer null pour le lpLocalName et le lpProvider. Le dwType doit être RESOURCETYPE_DISK. Le lpRemoteName doit être \\ ComputerName.
la source
WNetUseConnection
doivent-elles être fermées manuellement en appelantWNetCancelConnection2
? Ou y a-t-il un délai d'inactivité (ou un autre mécanisme) et nous n'avons pas à nous soucier?Pour les personnes à la recherche d'une solution rapide, vous pouvez utiliser le que
NetworkShareAccesser
j'ai écrit récemment (basé sur cette réponse (merci beaucoup!)):Usage:
AVERTISSEMENT: assurez-vous absolument que celui
Dispose
deNetworkShareAccesser
est appelé (même si votre application plante!), Sinon une connexion ouverte restera sous Windows. Vous pouvez voir toutes les connexions ouvertes en ouvrant l'cmd
invite et en entrantnet use
.Le code:
la source
using System.Runtime.InteropServices;
etusing System.ComponentModel;
pourDllImport
etWin32Exception
AFAIK, vous n'avez pas besoin de mapper le chemin UNC à une lettre de lecteur afin d'établir les informations d'identification pour un serveur. J'utilisais régulièrement des scripts batch comme:
Cependant, tout programme exécuté sur le même compte que votre programme pourra toujours accéder à tout ce qui
username:password
a accès. Une solution possible pourrait être d'isoler votre programme dans son propre compte d'utilisateur local (l'accès UNC est local sur le compte qui a appeléNET USE
).Remarque: utilisation de SMB dans tous les domaines n'est pas une bonne utilisation de la technologie, IMO. Si la sécurité est si importante, le fait que SMB manque de cryptage est un peu un frein en soi.
la source
NET USE
, cela pourrait être une approche viable. Êtes-vous certain que nous devons utiliser un compte local? L'NET USE
appel ne serait-il pas local sur la machine sur laquelle il a été appelé? Vous m'avez donné un bon chemin de recherchePlutôt que WNetUseConnection, je recommanderais NetUseAdd . WNetUseConnection est une fonction héritée qui a été remplacée par WNetUseConnection2 et WNetUseConnection3, mais toutes ces fonctions créent un périphérique réseau visible dans l'Explorateur Windows. NetUseAdd est l'équivalent de l'appel net use dans une invite DOS pour s'authentifier sur un ordinateur distant.
Si vous appelez NetUseAdd, les tentatives suivantes pour accéder au répertoire devraient réussir.
la source
Bien que je ne me connaisse pas, j'espère certainement que le n ° 2 est incorrect ... J'aimerais penser que Windows ne va pas donner AUTOMATIQUEMENT mes informations de connexion (surtout mon mot de passe!) À aucune machine , encore moins une qui ne fait pas partie de ma confiance.
Quoi qu'il en soit, avez-vous exploré l'architecture de l'usurpation d'identité? Votre code va ressembler à ceci:
Dans ce cas, la
token
variable est un IntPtr. Afin d'obtenir une valeur pour cette variable, vous devrez appeler la fonction API Windows LogonUser non gérée. Un petit tour sur pinvoke.net nous donne la signature suivante:Le nom d'utilisateur, le domaine et le mot de passe devraient sembler assez évidents. Jetez un œil aux différentes valeurs qui peuvent être transmises à dwLogonType et dwLogonProvider pour déterminer celle qui répond le mieux à vos besoins.
Ce code n'a pas été testé, car je n'ai pas de deuxième domaine ici où je puisse le vérifier, mais cela devrait, espérons-le, vous mettre sur la bonne voie.
la source
Ici une classe POC minimale avec toute la cruft supprimée
Vous pouvez directement utiliser
\\server\share\folder
w /WNetUseConnection
, pas besoin de le déshabiller\\server
uniquement au préalable.la source
La plupart des serveurs SFTP prennent également en charge SCP, ce qui peut être beaucoup plus facile à trouver des bibliothèques. Vous pouvez même simplement appeler un client existant à partir de votre code comme pscp inclus avec PuTTY .
Si le type de fichier avec lequel vous travaillez est quelque chose de simple comme un fichier texte ou XML, vous pouvez même aller jusqu'à écrire votre propre implémentation client / serveur pour manipuler le fichier en utilisant quelque chose comme .NET Remoting ou des services Web.
la source
J'ai vu l'option 3 implémentée avec les outils JScape de manière assez simple. Vous pourriez essayer. Ce n'est pas gratuit, mais cela fait son travail.
la source
Je joins mon code vb.net basé sur la référence brian
comment l'utiliser
la source
J'ai regardé MS pour trouver les réponses. La première solution suppose que le compte d'utilisateur exécutant le processus d'application a accès au dossier ou au lecteur partagé (même domaine). Assurez-vous que votre DNS est résolu ou essayez d'utiliser l'adresse IP. Procédez simplement comme suit:
Si vous voulez sur différents domaines .NET 2.0 avec des informations d'identification, suivez ce modèle:
la source