2010-05-07 11 views
6

Tengo una página ASP clásica, escrita en JScript, que usa Scripting.FileSystemObject para guardar archivos en un recurso compartido de red, y no funciona. ("Permiso denegado")Permisos de archivo con FileSystemObject: CScript.exe dice una cosa, ASP clásico dice otra

La página ASP se ejecuta en IIS mediante la autenticación de Windows, la suplantación habilitada.

Si funciono el siguiente bloque de código localmente a través de CScript.exe:

var objNet = new ActiveXObject("WScript.Network"); 
WScript.Echo(objNet.ComputerName); 
WScript.Echo(objNet.UserName); 
WScript.Echo(objNet.UserDomain); 

var fso = new ActiveXObject("Scripting.FileSystemObject"); 
var path = "\\\\myserver\\my_share\\some_path"; 
if (fso.FolderExists(path)) { 
    WScript.Echo("Yes"); 
} else { 
    WScript.Echo("No"); 
} 

consigo la salida (esperado):

MY_COMPUTER 
dylan.beattie 
MYDOMAIN 
Yes 

Si funciono el mismo código como parte de una página .ASP, sustituyendo Response.Write para WScript.Echo me da este resultado:

MY_COMPUTER 
dylan.beattie 
MYDOMAIN 
No 

ahora - a mi entender º en el objeto WScript.Network recuperará las credenciales de seguridad actuales del hilo que realmente está ejecutando el código. Si esto es correcto, ¿por qué el mismo usuario, en el mismo dominio, obtiene resultados diferentes de CScript.exe frente a ASP? Si mi código ASP es ejecutándose como dylan.beattie, ¿por qué no puedo ver el recurso compartido de red? Y si es no ejecutándose como dylan.beattie, ¿por qué WScript.Network cree que es?

Respuesta

4

El problema es obvio. En la implementación actual solo tiene suplantación de usuarios y ninguna delegación. No quiero repetir información ya escrita por Stephen Martin. Solo quiero agregar al menos tres soluciones. La forma clásica de delegación que sugiere Stephen Martin es de una sola manera. Puede leer algunas formas más aquí: http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_delegation. Veo tres formas prácticas de que la solución de su problema:

  1. convertir el testigo de suplantación del usuario a una ficha con el nivel de delegación de suplantación o para un nuevo identificador primario. Puede hacer esto con respecto a DuplicateToken o DuplicateTokenEx.

  2. Uso S4U2Self (ver http://msdn.microsoft.com/en-us/magazine/cc188757.aspx y http://msdn.microsoft.com/en-us/library/ms998355.aspx) para recibir un nuevo token de la anterior con respecto a uno sencillo.NET instrucción WindowsIdentity wi = new WindowsIdentity(identity);

  3. Puede acceder a otro servidor con respecto a una cuenta fija. Puede ser una cuenta de equipo en una cuenta del grupo de aplicaciones de IIS. Puede ser otra cuenta definida fija que solo se usará para acceder al sistema de archivos.

Es importante saber qué versión de Windows Server que tiene en el servidor donde se ejecuta IIS y qué nivel de función de dominio que tiene en Active Directory para el dominio (que ver esto en "dominio de Active Directory y Fideicomisos "herramienta si selecciona su dominio y elige" Elevar el nivel funcional del dominio "). También es interesante saber bajo qué cuenta se ejecuta el grupo de aplicaciones de IIS.

La primera y la tercera forma siempre funcionarán. La tercera forma puede ser mala para su entorno y para el permiso actual en el sistema de archivos. El segundo es muy elegante. Permite el control de los servidores (servidor de archivos) a los que se accede desde IIS. De esta manera tiene algunas restricciones y necesita algo de trabajo por hacer en Active Directory.

Debido a que usa ASP clásico, se debe crear un pequeño componente de software de secuencias de comandos para respaldar su implementación.

¿De qué manera prefieres?

ACTUALIZADO en base a la pregunta de comentario: Debido a que utiliza ASP clásico no se puede usar una API de Win32 directamente, pero se puede escribir un pequeño componente COM en Visual Basic 6 o en .NET que utilizan las API que se necesita. Como ejemplo, puede usar el código de http://support.microsoft.com/kb/248187/en. Pero deberías hacer algunas otras cosas adentro. Entonces explico ahora qué API de Win32 puede ayudarlo a hacer todo lo que necesita con tokens y suplantación.

Antes que nada, una pequeña explicación sobre la suplantación. Todo funciona muy facilmente Siempre hay un token primario bajo el cual se ejecuta el proceso. A cualquier hilo se le puede asignar otro token (token de hilo). Para hacer esto uno necesita tener un token de un usuario hUserToken y llamar a la API ImpersonateLoggedOnUser(hUserToken);.

Para volver al token de proceso original (para el hilo actual solamente) puede llamar a la función RevertToSelf(). La señal del usuario será recibida y ya suplantada por IIS, ya que usted configuró su sitio web. Para volver al token de proceso original, debe implementar la llamada de la función RevertToSelf() en su componente COM personalizado. Probablemente, si no necesita hacer nada más en la página ASP, será suficiente, pero le recomiendo que tenga más cuidado y guarde el token de los usuarios actuales en una variable antes de utilizar los archivos. Luego realiza todas las operaciones con el sistema de archivos y al final reasigna el token de los usuarios nuevamente al hilo actual. Puede asignar un token de suplantación a un hilo con respecto a SetThreadToken(NULL,hUserToken);. Para dar (guardar) token de hebra actual (token de usuario en su caso) puede usar OpenThreadToken API. Debe funcionar.

ACTUALIZADO 2: Es probable que el uso de la función RevertToSelf()al final de una página ASP ya estaría bien para ti. El código C# correspondiente puede ser así:

Cree un nuevo proyecto en C# del tipo "Biblioteca de clases" con el nombre LoginAdmin. Pegue el siguiente código dentro de

using System; 
using System.Runtime.InteropServices; 

namespace LoginAdmin { 
    [InterfaceTypeAttribute (ComInterfaceType.InterfaceIsDual)] 
    public interface IUserImpersonate { 
     [DispId(1)] 
     bool RevertToSelf(); 
    } 

    internal static class NativeMethods { 
     [DllImport ("advapi32.dll", SetLastError = true)] 
     internal static extern bool RevertToSelf(); 
    } 

    [ClassInterface (ClassInterfaceType.AutoDual)] 
    public class UserImpersonate : IUserImpersonate { 
     public UserImpersonate() { } 

     public bool RevertToSelf() { 
      return NativeMethods.RevertToSelf(); 
     } 
    } 
} 

Compruebe las propiedades del proyecto en la parte "Crear" de "Registrarse para la interoperabilidad COM".En la parte "Firma" del proyecto, compruebe el ensamblaje y en "Elija un archivo de clave de nombre seguro" elija <New...>, luego escriba cualquier nombre de archivo y contraseña (o marque "proteger mi clave ..."). Al final se debe modificar una línea de AssemblyInfo.cs en Propiedades parte del proyecto:

[assembly: ComVisible (true)] 

Después de compilar este proyecto que se produzcan dos archivos, LoginAdmin.dll y LoginAdmin.tlb. La DLL ya está registrada en la computadora actual. Para registrarse, en la otra computadora, use RegAsm.exe.

Para probar esta DLL COM en una página ASP que puede hacer siguiendo

<%@ Language="javascript" %> 
<html><body> 
    <% var objNet = Server.CreateObject("WScript.Network"); 
     Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>"); 
     Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>"); 

     var objLoginAdmin = Server.CreateObject("LoginAdmin.UserImpersonate"); 
     var isOK = objLoginAdmin.RevertToSelf(); 
     if (isOK) 
       Response.Write("RevertToSelf return true<br/>"); 
     else 
       Response.Write("RevertToSelf return false<br/>"); 
     Response.Write("One more time after RevertToSelf()<br/>"); 
     Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>"); 
     Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>"); 

     var fso = Server.CreateObject("Scripting.FileSystemObject"); 
     var path = "\\\\mk01\\C\\Oleg"; 
     if (fso.FolderExists(path)) { 
      Response.Write("Yes"); 
     } else { 
      Response.Write("No"); 
     }%> 
</body></html> 

Si la cuenta utilizada para ejecutar el grupo de aplicaciones IIS tiene acceso a la correspondiente recurso compartido de red, la salida se ve como después de

Current user: Oleg 
Current user's domain: WORKGROUP 
RevertToSelf return true 
One more time after RevertToSelf() 
Current user: DefaultAppPool 
Current user's domain: WORKGROUP 
Yes 
+0

Bien, entonces, si estoy usando una suplantación, ¿qué credenciales usará el servidor cuando intente acceder a un recurso de red? Estoy muy contento de configurar el acceso a la red para la cuenta del equipo de IIS o la cuenta del grupo de aplicaciones, pero solo necesito saber exactamente a qué cuenta se le debe otorgar acceso. Si el grupo de aplicaciones se ejecuta como MYDOMAIN \ Some_Special_User, ¿utilizará la seguridad de Windows con suplantación para anular esta identidad cuando acceda a los recursos de la red? –

4

Bajo suplantación sólo se puede acceder a los recursos que se pueden proteger en el equipo local no se puede acceder a cualquier cosa en la red.

En Windows cuando se está ejecutando como un usuario representado está ejecutando bajo lo que se llama una red Token. Este token tiene las credenciales del usuario para el acceso de la computadora local, pero no tiene credenciales para el acceso remoto. Entonces, cuando accedes al recurso compartido de red, en realidad estás accediéndolo como usuario anónimo.

Cuando está ejecutando un proceso en su escritorio (como CScript.exe), entonces se está ejecutando bajo un token de Usuario interactivo. Este token tiene credenciales completas para acceso local y remoto, por lo que puede acceder al recurso compartido de red.

Con el fin de acceder a recursos remotos, mientras que hacerse pasar por un usuario de Windows debe utilizar Delegación en lugar de suplantación. Esto implicará algunos cambios en su directorio activo para permitir la delegación de la computadora y/o los usuarios de su dominio. Esto puede ser un riesgo de seguridad, por lo que debe revisarse cuidadosamente.

Cuestiones relacionadas