Nos hemos encontrado con una situación interesante que debe resolverse, y mis búsquedas han resultado nulas. Por lo tanto, pido ayuda a la comunidad SO.
El problema es este: tenemos la necesidad de acceder mediante programación a un archivo compartido que no está en nuestro dominio, y no está dentro de un dominio externo confiable a través del uso compartido remoto de archivos / UNC. Naturalmente, necesitamos suministrar credenciales a la máquina remota.
Por lo general, uno resuelve este problema de una de dos maneras:
- Asigne el recurso compartido de archivos como una unidad y proporcione las credenciales en ese momento. Esto normalmente se hace usando el
NET USE
comando o las funciones de Win32 que se duplicanNET USE
. - Acceda al archivo con una ruta UNC como si la computadora remota estuviera en el dominio y asegúrese de que la cuenta con la que se ejecuta el programa esté duplicada (incluida la contraseña) en la máquina remota como usuario local. Básicamente aprovecha el hecho de que Windows proporcionará automáticamente las credenciales del usuario actual cuando el usuario intente acceder a un archivo compartido.
- No use el uso compartido de archivos a distancia. Use FTP (o algún otro medio) para transferir el archivo, trabaje en él localmente y luego vuélvalo a transferir.
Por diversas y diversas razones, nuestros arquitectos de seguridad / redes han rechazado los dos primeros enfoques. El segundo enfoque es obviamente un agujero de seguridad; Si la computadora remota se ve comprometida, la computadora local está ahora en riesgo. El primer enfoque es insatisfactorio porque la unidad recién montada es un recurso compartido disponible para otros programas en la computadora local durante el acceso al archivo por parte del programa. Aunque es bastante posible hacer que esto sea temporal, sigue siendo un agujero en su opinión.
Están abiertos a la tercera opción, pero los administradores de la red remota insisten en SFTP en lugar de FTPS, y FtpWebRequest solo admite FTPS. SFTP es la opción más amigable con el firewall y hay un par de bibliotecas que podría usar para ese enfoque, pero preferiría reducir mis dependencias si pudiera.
He buscado en MSDN un medio administrado o win32 para usar el intercambio remoto de archivos, pero no he podido encontrar nada útil.
Y entonces pregunto: ¿Hay otra manera? ¿Me perdí una función win32 súper secreta que hace lo que quiero? ¿O debo buscar alguna variante de la opción 3?
fuente
Respuestas:
La forma de resolver su problema es usar una API Win32 llamada WNetUseConnection .
Use esta función para conectarse a una ruta UNC con autenticación, NO para asignar una unidad .
Esto le permitirá conectarse a una máquina remota, incluso si no está en el mismo dominio, e incluso si tiene un nombre de usuario y contraseña diferentes.
Una vez que haya utilizado WNetUseConnection, podrá acceder al archivo a través de una ruta UNC como si estuviera en el mismo dominio. La mejor manera es probablemente a través de las acciones administrativas integradas.
Ejemplo: \\ computername \ c $ \ program files \ Folder \ file.txt
Aquí hay un código C # de muestra que usa WNetUseConnection.
Tenga en cuenta que, para NetResource, debe pasar nulo para lpLocalName y lpProvider. El dwType debe ser RESOURCETYPE_DISK. El lpRemoteName debe ser \\ ComputerName.
fuente
WNetUseConnection
cerrarse manualmente llamandoWNetCancelConnection2
? ¿O hay un tiempo de espera inactivo (o algún otro mecanismo) y no tenemos que molestarnos?Para las personas que buscan una solución rápida, pueden usar la
NetworkShareAccesser
que escribí recientemente (basada en esta respuesta (¡muchas gracias!)):Uso:
ADVERTENCIA: Por favor, haga absolutamente seguro, que
Dispose
de laNetworkShareAccesser
que se llama (incluso si APP choques!), De lo contrario una conexión abierta permanecerá en Windows. Puede ver todas las conexiones abiertas abriendo elcmd
indicador e ingresandonet use
.El código:
fuente
using System.Runtime.InteropServices;
yusing System.ComponentModel;
paraDllImport
yWin32Exception
AFAIK, no necesita asignar la ruta UNC a una letra de unidad para establecer credenciales para un servidor. Usé regularmente scripts por lotes como:
Sin embargo, cualquier programa que se ejecute en la misma cuenta que su programa aún podría acceder a todo lo que
username:password
tiene acceso. Una posible solución podría ser aislar su programa en su propia cuenta de usuario local (el acceso UNC es local a la cuenta que llamóNET USE
).Nota: El uso de SMB entre dominios no es un buen uso de la tecnología, IMO. Si la seguridad es tan importante, el hecho de que SMB carece de cifrado es un poco un obstáculo por sí solo.
fuente
NET USE
, ese podría ser un enfoque viable. Sin embargo, ¿está seguro de que necesitamos usar una cuenta local? ¿No sería laNET USE
llamada local a la máquina en la que se llamó? Me has dado un buen camino de investigaciónEn lugar de WNetUseConnection, recomendaría NetUseAdd . WNetUseConnection es una función heredada que ha sido reemplazada por WNetUseConnection2 y WNetUseConnection3, pero todas esas funciones crean un dispositivo de red que es visible en el Explorador de Windows. NetUseAdd es el equivalente a llamar al uso de la red en un indicador de DOS para autenticarse en una computadora remota.
Si llama a NetUseAdd, los intentos posteriores de acceder al directorio deberían tener éxito.
fuente
Si bien no me conozco, ciertamente espero que el número 2 sea incorrecto ... Me gustaría pensar que Windows no va a dar AUTOMÁTICAMENTE mi información de inicio de sesión (¡menos que nada mi contraseña!) A ninguna máquina , mucho menos uno que no es parte de mi confianza.
De todos modos, ¿ha explorado la arquitectura de suplantación? Su código se verá similar a esto:
En este caso, la
token
variable es un IntPtr. Para obtener un valor para esta variable, deberá llamar a la función API de Windows LogonUser no administrada. Un viaje rápido a pinvoke.net nos da la siguiente firma:El nombre de usuario, el dominio y la contraseña deberían parecer bastante obvios. Eche un vistazo a los diversos valores que se pueden pasar a dwLogonType y dwLogonProvider para determinar cuál se adapta mejor a sus necesidades.
Este código no se ha probado, ya que no tengo un segundo dominio aquí donde pueda verificarlo, pero espero que esto lo ponga en el camino correcto.
fuente
Aquí una clase mínima de POC con todo el cruft eliminado
Puede usar directamente
\\server\share\folder
w /WNetUseConnection
, no es necesario despojarlo a la\\server
parte solo de antemano.fuente
La mayoría de los servidores SFTP también admiten SCP, lo que puede ser mucho más fácil para encontrar bibliotecas. Incluso podría llamar a un cliente existente desde su código como pscp incluido con PuTTY .
Si el tipo de archivo con el que está trabajando es algo simple, como un archivo de texto o XML, incluso podría llegar a escribir su propia implementación de cliente / servidor para manipular el archivo usando algo como .NET Remoting o servicios web.
fuente
He visto la opción 3 implementada con herramientas JScape de una manera bastante sencilla. Puedes intentarlo. No es gratis, pero hace su trabajo.
fuente
adjunto mi código vb.net basado en la referencia de brian
cómo usarlo
fuente
Miré a MS para encontrar las respuestas. La primera solución supone que la cuenta de usuario que ejecuta el proceso de la aplicación tiene acceso a la carpeta o unidad compartida (mismo dominio). Asegúrese de que su DNS esté resuelto o intente usar la dirección IP. Simplemente haga lo siguiente:
Si desea en diferentes dominios .NET 2.0 con credenciales, siga este modelo:
fuente