Cuando se conecta a un recurso compartido de red para el cual el usuario actual (en mi caso, un usuario de servicio habilitado para la red) no tiene derechos, se deben proporcionar nombre y contraseña.
Sé cómo hacer esto con las funciones de Win32 (la WNet*
familia de mpr.dll
), pero me gustaría hacerlo con la funcionalidad .Net (2.0).
¿Qué opciones hay disponibles?
Tal vez más información ayude:
- El caso de uso es un servicio de Windows, no una aplicación Asp.Net.
- El servicio se ejecuta bajo una cuenta que no tiene derechos sobre el recurso compartido.
- La cuenta de usuario necesaria para el recurso compartido no se conoce en el lado del cliente.
- El cliente y el servidor no son miembros del mismo dominio.
Respuestas:
Puede cambiar la identidad del hilo o P / Invocar WNetAddConnection2. Prefiero el último, ya que a veces necesito mantener múltiples credenciales para diferentes ubicaciones. Lo envuelvo en un IDisposable y llamo a WNetCancelConnection2 para eliminar los créditos después (evitando el error de múltiples nombres de usuario):
fuente
Me gustó tanto la respuesta de Mark Brackett que hice mi propia implementación rápida. Aquí está si alguien más lo necesita a toda prisa:
fuente
throw new Win32Exception(result);
, ya que WNetAddConnection2 devuelve códigos de error win32 (ERROR_XXX
)NetworkCredential
objeto, la aplicación pudo conectarse una vez a la unidad de red. Después de eso obtuvimos un ERROR_LOGON_FAILURE en cada intento hasta que se reinició la aplicación. Luego intentamos proporcionar el dominio en elNetworkCredential
objeto también, ¡y de repente funcionó! No tengo idea de por qué esto solucionó el problema, especialmente el hecho de que funcionó para conectarse una vez sin el dominio.Hoy, 7 años después, me enfrento al mismo problema y me gustaría compartir mi versión de la solución.
Está listo para copiar y pegar :-) Aquí está:
Paso 1
En su código (siempre que necesite hacer algo con permisos)
Paso 2
El archivo de ayuda que hace una magia
fuente
Busqué muchos métodos y lo hice a mi manera. Tiene que abrir una conexión entre dos máquinas a través del comando NET USE del símbolo del sistema y después de terminar su trabajo, borre la conexión con el comando NET USE "myconnection" / delete.
Debe usar el proceso del símbolo del sistema desde el código detrás de esta manera:
El uso es simple:
Aquí hay funciones:
Y también la función ExecuteCommand es:
Esta función funcionó muy rápido y estable para mí.
fuente
La solución de Luke Quinane se ve bien, pero funcionó solo parcialmente en mi aplicación ASP.NET MVC. Teniendo dos recursos compartidos en el mismo servidor con credenciales diferentes, podría usar la suplantación solo para el primero.
El problema con WNetAddConnection2 también es que se comporta de manera diferente en diferentes versiones de Windows. Es por eso que busqué alternativas y encontré la función LogonUser . Aquí está mi código que también funciona en ASP.NET:
Uso:
fuente
Para VB.lovers, el equivalente VB.NET del código de Luke Quinane (¡gracias Luke!)
fuente
Una opción que podría funcionar es usar
WindowsIdentity.Impersonate
(y cambiar el hilo principal) para convertirse en el usuario deseado, como así . De vuelta a p / invoke, sin embargo, me temo ...Otra opción descarada (e igualmente lejos de ser ideal) podría ser generar un proceso para hacer el trabajo ...
ProcessStartInfo
acepta un.UserName
,.Password
y.Domain
.Finalmente, ¿tal vez ejecutar el servicio en una cuenta dedicada que tenga acceso?(eliminado ya que ha aclarado que esto no es una opción).fuente
OK ... puedo volver a vender ...
Descargo de responsabilidad: Acabo de pasar un día de más de 18 horas (de nuevo) ... Soy viejo y olvidadizo ... No puedo deletrear ... Tengo un período de atención corto, así que mejor respondo rápido ... :-)
Pregunta:
¿Es posible cambiar el hilo principal a un usuario sin cuenta en la máquina local?
Responder:
Sí, puede cambiar un hilo principal incluso si las credenciales que está utilizando no están definidas localmente o están fuera del "bosque".
Me encontré con este problema al intentar conectarme a un servidor SQL con autenticación NTLM desde un servicio. Esta llamada utiliza las credenciales asociadas con el proceso, lo que significa que necesita una cuenta local o una cuenta de dominio para autenticarse antes de poder suplantar. Bla, bla ...
Pero...
Llamar a LogonUser (..) con el atributo ???? _ NEW_CREDENTIALS devolverá un token de seguridad sin intentar autenticar las credenciales. Kewl .. No tiene que definir la cuenta dentro del "bosque". Una vez que tenga el token, es posible que tenga que llamar a DuplicateToken () con la opción de habilitar la suplantación que da como resultado un nuevo token. Ahora llame a SetThreadToken (NULL, token); (¿Podría ser & token?) .. Una llamada a ImpersonateLoggedonUser (token); puede ser requerido, pero no lo creo. Búscalo ..
Haz lo que necesitas hacer..
Llame a RevertToSelf () si llamó a ImpersonateLoggedonUser () y luego a SetThreadToken (NULL, NULL); (Creo ... búscalo), y luego CloseHandle () en los controladores creados ...
No hay promesas, pero esto funcionó para mí ... ¡Esto está fuera de mi cabeza (como mi cabello) y no puedo deletrear!
fuente
Si no puede crear un token de seguridad válido localmente, parece que ha descartado todas las opciones de la barra de Win32 API y WNetAddConnection *.
Toneladas de información en MSDN sobre WNet - PInvoca información y código de muestra que se conecta a una ruta UNC aquí:
Referencia de MSDN aquí:
fuente
También portado a F # para usar con FAKE
fuente
Debería buscar agregar un me gusta como este:
En su web.config.
Más información.
fuente