2010-02-05 18 views
2

Je souhaite lister tous les fichiers d'un dossier auquel un utilisateur a accès en lecture. L'utilisateur visite le site Web et peut utiliser l'authentification par formulaire pour certains aspects du site (par exemple ajouter des liens, etc.), mais je souhaite lister les fichiers dans un dossier donné en utilisant ses informations d'identification Windows (puisque l'accès anonyme est désactivé). ne peut pas lire. Toutefois, lors de l'utilisation de Directory.GetFiles, il inclut également des fichiers qui ne peuvent pas être lus (bien que les métadonnées (taille du fichier, date de création, etc.) puissent être lues).Liste des fichiers auxquels l'utilisateur a accès en lecture (ASP.NET)

C'est ce que j'ai:

string[] files; 
string[] folders; 
string rootDir = @"\\server\path\to\dir\"; 
WindowsIdentity id = (WindowsIdentity)User.Identity ; 
using (System.Security.Principal.WindowsImpersonationContext context = System.Security.Principal.WindowsIdentity.Impersonate(id.Token)) 
{ 
     files = Directory.GetFiles(rootDir); 
     folders = Directory.GetDirectories(rootDir); 

     foreach (string file in files) 
     { 
      FileInfo fi = new FileInfo(file); 
      FileSecurity fs = fi.GetAccessControl(AccessControlSections.Access); 
      //foreach (FileSystemAccessRule rule in fs.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))) 
      //{ 
      // Response.Write((FileSystemRights.Read & rule.FileSystemRights) + " <br />"); 
      //} 

      Response.Write(file + " " + fi.Length + "<br />"); 
     } 
     context.Undo(); 
} 

Lorsque je visite la page, je reçois UnauthorizedAccessException dès que je l'utilise GetAccessControl, même si elle devrait utiliser les informations d'identification de l'utilisateur actuel. La suppression du using échoue car le compte asp.net n'a pas accès au dossier. Lorsque FileSecurity est mis en commentaire, il répertorie tous les fichiers.

Stack Trace:

[UnauthorizedAccessException: Attempted to perform an unauthorized operation.] 
    System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType resourceType, String name, SafeHandle handle, AccessControlSections accessControlSections, RawSecurityDescriptor& resultSd) +697 
    System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext) +63 
    System.Security.AccessControl.FileSystemSecurity..ctor(Boolean isContainer, String name, AccessControlSections includeSections, Boolean isDirectory) +86 
    System.Security.AccessControl.FileSecurity..ctor(String fileName, AccessControlSections includeSections) +42 
    System.IO.FileInfo.GetAccessControl(AccessControlSections includeSections) +29 
    UNCDirectory.Page_Load(Object sender, EventArgs e) +213 
    System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14 
    System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35 
    System.Web.UI.Control.OnLoad(EventArgs e) +99 
    System.Web.UI.Control.LoadRecursive() +50 
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627 

Toute idée de la façon dont je peux le faire, sans avoir recours à essayer d'ouvrir chaque fichier et attraper l'exception qui se produit?

Répondre

2

Géré pour le réparer. Lorsque vous refusez Read sur un fichier, il refuse également les autorisations de lecture, d'où le UnauthorizedAccessException. Donc, en utilisant try... catch ... semble que c'est la seule option.

Il est possible d'empêcher l'exception si Read est refusé et que ReadPermissions est autorisé (sous Paramètres avancés). Cela gère à la fois:

string[] files; 
string[] folders; 
WindowsIdentity id = (WindowsIdentity)User.Identity; 
using (System.Security.Principal.WindowsImpersonationContext context = id.Impersonate()) 
{ 
    files = Directory.GetFiles(RootDir); 
    folders = Directory.GetDirectories(RootDir); 

    foreach (string file in files) 
    { 
     FileInfo fi = new FileInfo(file); 
     FileSecurity fs = null; 
     try 
     { 
      fs = fi.GetAccessControl(AccessControlSections.Access); 
     } 
     catch (UnauthorizedAccessException) 
     { 
      goto Next; 
     } 
     foreach (FileSystemAccessRule rule in fs.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))) 
     { 
      if (id.User.CompareTo(rule.IdentityReference as SecurityIdentifier) == 0) 
      { 
       if(rule.AccessControlType.ToString() == "Deny" && 
        rule.FileSystemRights.ToString().Contains("ReadData")) 
       { 
        goto Next; 
       } 
      } 
     } 

     Response.Write(file + " " + fi.Length + "<br />"); 
     // next in sequence. label for goto 
     Next: ; 
    } 
    context.Undo(); 
} 

maintenant les fichiers peuvent être répertoriés dans un répertoire (en utilisant l'usurpation d'identité) sans donner le compte ASP.NET (généralement service réseau) d'accès aussi bien.

+2

Je déteste nitpick ... mais pourquoi utilisez-vous goto et une étiquette? juste casser ou continuer comme nécessaire. –

+0

Pause éprouvée, mais elle casse seulement la file d'attente de FileAccessRule foreach .. a voulu sortir de lui et continuer au prochain fichier. Bien que je suppose qu'un bool pourrait avoir été utilisé ... L'étiquette n'est pas bonne à utiliser et si oui, pourquoi pas? – SamWM

+2

Goto est idéal pour sortir des boucles imbriquées. Il simplifie la logique et augmente les performances dans de nombreux cas en évitant les ruptures conditionnelles inutiles à chaque niveau de boucle. – Triynko

1

Vous devez probablement configurer Windows/Integrated Authentication dans asp.net/IIS. http://msdn.microsoft.com/en-us/library/aa292114(VS.71).aspx

+0

Le site utilise l'authentification intégrée et le fait qu'il puisse récupérer la liste des fichiers montre que c'est le cas (sinon il y aura une exception - différente de celle que j'obtiens). L'erreur se produit lorsque vous essayez d'obtenir les règles d'accès pour un fichier. – SamWM