2010-05-07 5 views
6

Ich habe eine klassische ASP-Seite - in JScript geschrieben - das Scripting.FileSystemObject verwendet, um Dateien auf einer Netzwerkfreigabe zu speichern - und es funktioniert nicht. ("Berechtigung verweigert")Dateiberechtigungen mit FileSystemObject - CScript.exe sagt eine Sache, Classic ASP sagt eine andere

Die ASP-Seite wird unter IIS mit Windows-Authentifizierung ausgeführt, wobei Identitätswechsel aktiviert ist.

Wenn ich den folgenden Code-Block lokal über 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"); 
} 

Ich erhalte die (erwartete) Ausgabe:

MY_COMPUTER 
dylan.beattie 
MYDOMAIN 
Yes 

Wenn ich laufen den gleichen Code als Teil eines .ASP Seite, unter Substitution von Response.Write für WScript.Echo bekomme ich diese Ausgabe:

MY_COMPUTER 
dylan.beattie 
MYDOMAIN 
No 

jetzt - mein Verständnis ist th WScript.Network-Objekt ruft die aktuellen Sicherheitsanmeldeinformationen des Threads ab, auf dem der Code tatsächlich ausgeführt wird. Wenn dies richtig ist - warum erhält derselbe Benutzer auf derselben Domäne unterschiedliche Ergebnisse von CScript.exe vs ASP? Wenn mein ASP-Code als dylan.beattie läuft, warum kann ich dann die Netzwerkfreigabe nicht sehen? Und wenn es nicht läuft als dylan.beattie, warum denkt WScript.Network es ist?

Antwort

4

Ihr Problem ist klar. In der aktuellen Implementierung haben Sie nur den Identitätswechsel von Benutzern und keine Delegierung. Ich möchte die bereits von Stephen Martin geschriebenen Informationen nicht wiederholen. Ich möchte nur mindestens drei Lösungen hinzufügen. Die klassische Art der Delegation, die Stephen Martin vorschlägt, ist nur eine Möglichkeit. Sie können hier einige weitere Möglichkeiten lesen: http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_delegation. Ich sehe drei praktische Möglichkeiten der Sie Ihr Problem lösen:

  1. umrechnen Identitätstoken des Benutzers zu einem Token mit Delegationsebene von Identitätswechsel oder zu einem neuen primären Token. Sie können dies in Bezug auf DuplicateToken oder DuplicateTokenEx tun.

  2. Verwenden S4U2Self (siehe http://msdn.microsoft.com/en-us/magazine/cc188757.aspx und http://msdn.microsoft.com/en-us/library/ms998355.aspx) ein neues Token aus der alten mit Bezug auf eine einfach zu erhalten.NET-Anweisung WindowsIdentity wi = new WindowsIdentity(identity);

  3. Sie können auf einen anderen Server mit einem festen Konto zugreifen. Es kann ein Computerkonto auf einem Konto des Anwendungspools des IIS sein. Es kann sich um ein anderes fest definiertes Konto handeln, das nur für den Zugriff auf das Dateisystem verwendet wird.

Es ist wichtig, welche Version von Windows Server zu wissen, dass Sie auf dem Server, auf dem IIS ausgeführt wird und die Domain-Funktionslevel Sie haben dies in „Active Directory-Domäne und Trusts in Active Directory für Ihre Domain (Sie sehen "Werkzeug, wenn Sie Ihre Domain auswählen und" Domain Function Level erhöhen "wählen. Es ist auch interessant zu wissen, unter welchem ​​Konto der Anwendungspool des IIS ausgeführt wird.

Der erste und der dritte Weg werden immer funktionieren. Der dritte Weg kann für Ihre Umgebung und für die aktuelle Berechtigung im Dateisystem schlecht sein. Der zweite ist sehr elegant. Es ermöglicht die Kontrolle darüber, auf welche Server (Dateiserver) von IIS zugegriffen wird. Dieser Weg hat einige Einschränkungen und es bedarf einiger Arbeit in Active Directory.

Da Sie klassisches ASP verwenden, muss eine kleine skriptfähige Softwarekomponente erstellt werden, um Ihre Implementierung zu unterstützen.

Welchen Weg bevorzugen Sie?

AKTUALISIERT basierend auf der Frage aus Kommentar: Da Sie klassischen ASP verwenden, können Sie nicht direkt eine Win32-API verwenden, aber Sie können eine kleine COM-Komponente in VB6 oder in .NET schreiben, die APIs verwenden, die Sie benötigen. Als Beispiel können Sie Code von http://support.microsoft.com/kb/248187/en verwenden. Aber du solltest andere Dinge drinnen machen. Also erkläre ich jetzt, welche Win32-API Ihnen helfen kann, alles, was Sie brauchen, mit Tokens und Identitätswechsel zu tun.

Zunächst eine kleine Erklärung über die Identität. Alles funktioniert sehr einfach. Es gibt immer ein primäres Token, unter dem der Prozess ausgeführt wird. Zu jedem Thread kann ein anderes Token (Thread-Token) zugewiesen werden. Um dies zu tun, muss man ein Token eines Benutzers hUserToken haben und API ImpersonateLoggedOnUser(hUserToken); aufrufen.

Um zum ursprünglichen Prozesstoken (nur für den aktuellen Thread) zurückzukehren, können Sie die Funktion RevertToSelf() aufrufen. Das Token des Benutzers wird von IIS empfangen und bereits von Ihnen imitiert, weil Sie Ihre Website so konfiguriert haben. Um zum ursprünglichen Prozesstoken zurückzukehren, sollten Sie den Aufruf der Funktion RevertToSelf() in Ihrer benutzerdefinierten COM-Komponente implementieren. Wahrscheinlich, wenn Sie nichts mehr auf der ASP-Seite tun müssen, wird es genug sein, aber ich empfehle Ihnen, vorsichtiger zu sein und das aktuelle Benutzer-Token in einer Variablen zu speichern, bevor Sie mit Dateien arbeiten. Dann machen Sie alle Operationen mit dem Dateisystem und weisen das Benutzer-Token am Ende wieder dem aktuellen Thread zu. Sie können einem Thread ein Identitätswechsel-Token in Bezug auf SetThreadToken(NULL,hUserToken); zuweisen. Um das aktuelle Thread-Token (Benutzer-Token in Ihrem Fall) zu geben (speichern), können Sie die API OpenThreadToken verwenden. Es muss funktionieren.

AKTUALISIERT 2: Wahrscheinlich ist die Nutzung von RevertToSelf() Funktion am Ende von einer ASP-Seite würde bereits für Sie in Ordnung sein. Der entsprechende C# -Code kann so lauten:

Erstellen Sie ein neues Projekt in C# vom Typ "Klassenbibliothek" mit dem Namen LoginAdmin. Fügen Sie den folgenden Code in

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(); 
     } 
    } 
} 

Einchecken Projekteigenschaften in "Build" Teil "Registrieren für COM-Interop".Unter "Signieren" einen Teil der Projektprüfung Unterschreiben Sie die Assembly und wählen Sie unter "Wählen Sie eine Schlüsseldatei mit starkem Namen aus" <New...>, geben Sie dann einen beliebigen Dateinamen und ein Passwort ein (oder kreuzen Sie "meinen Schlüssel schützen ..." an). Am Ende sollten Sie eine Linie von AssemblyInfo.cs in Properties Teil des Projekts ändern:

[assembly: ComVisible (true)] 

Nach dem Kompilieren dieses Projekt zwei Dateien erhalten, LoginAdmin.dll und LoginAdmin.tlb. Die DLL ist bereits auf dem aktuellen Computer registriert. Um zu registrieren, wenn auf dem anderen Computer RegAsm.exe verwenden.

diesen COM-DLL auf einer ASP-Seite testen Sie

<%@ 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> 

folgenden tun Wenn das Konto des IIS-Anwendungspool Zugang zu laufen verwendet, um die entsprechenden Netzwerkfreigabe hat, wird die Ausgabe wie folgt

aussehen wird
+0

OK, also, wenn ich Identitätswechsel verwende, welche Anmeldeinformationen wird der Server verwenden, wenn ich versuche, auf eine Netzwerkressource zuzugreifen? Ich bin ziemlich glücklich, den Netzwerkzugriff für das IIS-Computerkonto oder den Anwendungspool-Account einzurichten - aber ich muss nur genau herausfinden, welchem ​​Konto Zugriff gewährt werden soll! Wenn der Anwendungspool als MYDOMAIN \ Some_Special_User ausgeführt wird, überschreibt die Verwendung der Windows-Sicherheit mit Identitätswechsel diese Identität beim Zugriff auf Netzwerkressourcen tatsächlich? –

4

Unter Identitätswechsel können Sie nur auf sicherungsfähige Ressourcen auf dem lokalen Computer zugreifen, auf die Sie über das Netzwerk nicht zugreifen können.

Wenn Sie unter Windows als imitiertes Benutzer ausgeführt werden, führen Sie ein sogenanntes Netzwerk-Token aus. Dieses Token verfügt über die Anmeldeinformationen des Benutzers für den Zugriff auf den lokalen Computer, aber keine Anmeldeinformationen für den Remotezugriff. Wenn Sie also auf die Netzwerkfreigabe zugreifen, greifen Sie auf sie als anonymen Benutzer zu.

Wenn Sie auf Ihrem Desktop einen Prozess ausführen (z. B. CScript.exe), werden Sie unter einem interaktiven Benutzer-Token ausgeführt. Dieses Token verfügt über vollständige Anmeldeinformationen für den lokalen und den Remotezugriff, sodass Sie auf die Netzwerkfreigabe zugreifen können.

Um auf Remote-Ressourcen zugreifen zu können, während Sie sich als Windows-Benutzer ausgeben, müssen Sie Delegierung anstelle von Identitätswechsel verwenden. Dies erfordert einige Änderungen an Ihrem Active Directory, um die Delegierung für den Computer und/oder die Benutzer in Ihrer Domäne zu ermöglichen. Dies kann ein Sicherheitsrisiko darstellen, daher sollte es sorgfältig überprüft werden.