60 votes

Comment avez-vous vérifier les autorisations d'écriture sur un répertoire ou un fichier?

J'ai un programme qui écrit des données dans un fichier à l'aide d'une méthode comme celle ci-dessous.


public void ExportToFile(string filename)
{
     using(FileStream fstream = new FileStream(filename,FileMode.Create))
     using (TextWriter writer = new StreamWriter(fstream))
     {
         // try catch block for write permissions 
         writer.WriteLine(text);


     }
}

Lors de l'exécution du programme, j'obtiens une erreur:

Exception Non Gérée: System.UnauthorizedAccessException: le chemin d'Accès "mypath" est refusé.
 au Système.IO.__Erreur.WinIOError(Int32 errorCode, String maybeFullPath)
 au Système.IO.FileStream.Init(String path, FileMode mode, FileAccess accès,
nt32 droits, Boolean useRights, FileShare part, bufferSize Int32, FileOptions
ptions, SECURITY_ATTRIBUTES secattrs, Chaîne, Booléen bFromProxy)
 au Système.IO.FileStream..ctor(String path, FileMode mode, FileAccess accès
FileShare part, bufferSize Int32, FileOptions options, d'une Chaîne msgPath, Boolea
bFromProxy)

Question: Quel code dois-je prendre ce et comment dois-je accorder l'accès?

67voto

Josh Points 23923

Mise à JOUR:

Modifié le code sur la base de cette réponse pour se débarrasser de l'obsolescence des méthodes.

Vous pouvez utiliser la Sécurité de l'espace de noms pour vérifier:

public void ExportToFile(string filename)
{
    var permissionSet = new PermissionSet(PermissionState.None);    
    var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
    permissionSet.AddPermission(writePermission);

    if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
    {
        using (FileStream fstream = new FileStream(filename, FileMode.Create))
        using (TextWriter writer = new StreamWriter(fstream))
        {
            // try catch block for write permissions 
            writer.WriteLine("sometext");


        }
    }
    else
    {
        //perform some recovery action here
    }

}

Aussi loin que l'obtention des autorisations, vous allez avoir à demander à l'utilisateur de le faire pour vous en quelque sorte. Si vous pouviez par programmation à faire cela, alors nous serions tous dans la détresse ;)

30voto

Iain Points 2909

Lorsque votre code est le suivant:

  1. Vérifie le courant de l'utilisateur a la permission de faire quelque chose.
  2. Effectue l'action qui doit les droits vérifié dans 1.

Vous courez le risque que la modification des autorisations entre 1 et 2 parce que vous ne pouvez pas prédire ce qui va se passer sur le système lors de l'exécution. Par conséquent, votre code doit gérer la situation où un UnauthorisedAccessException est levée, même si vous avez déjà vérifié les autorisations.

Notez que le SecurityManager classe est utilisée pour vérifier le CAS des autorisations et ne fait pas de vérifier avec le système d'exploitation si l'utilisateur courant a accès en écriture à l'emplacement spécifié (par l'intermédiaire de Lca et As). En tant que tel, IsGranted retourne toujours vrai pour localement des applications en cours d'exécution.

Exemple (dérivé de Josh exemple):

//1. Provide early notification that the user does not have permission to write.
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
if(!SecurityManager.IsGranted(writePermission))
{
    //No permission. 
    //Either throw an exception so this can be handled by a calling function
    //or inform the user that they do not have permission to write to the folder and return.
}

//2. Attempt the action but handle permission changes.
try
{
    using (FileStream fstream = new FileStream(filename, FileMode.Create))
    using (TextWriter writer = new StreamWriter(fstream))
    {
    	writer.WriteLine("sometext");
    }
}
catch (UnauthorizedAccessException ex)
{
    //No permission. 
    //Either throw an exception so this can be handled by a calling function
    //or inform the user that they do not have permission to write to the folder and return.
}

C'est difficile et pas recommandé d'essayer d'en programmant calculer les autorisations effectives à partir du dossier basé sur le raw (Acl qui sont tous disponibles à travers le Système.De sécurité.AccessControl classes). D'autres réponses sur un Débordement de Pile et de l'ensemble de web vous recommandons d'essayer d'effectuer l'action de savoir si l'autorisation est accordée. Ce post résume ce qui est nécessaire pour mettre en œuvre l'autorisation de calcul et devrait être suffisant pour vous empêcher de faire cela.

6voto

Pablonete Points 552

Désolé, mais aucune des solutions précédentes m'ont aidé. J'ai besoin de vérifier les deux côtés: SecurityManager et DONC des autorisations. J'ai beaucoup appris avec Josh code et avec iain réponse, mais j'ai peur d'avoir besoin d'utiliser Rakesh code (grâce à lui). Un seul bug: j'ai trouvé qu'il vérifie seulement pour Permettre et non pas pour Refuser les autorisations. Donc ma proposition est:

        string folder;
        AuthorizationRuleCollection rules;
        try {
            rules = Directory.GetAccessControl(folder)
                .GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
        } catch(Exception ex) { //Posible UnauthorizedAccessException
            throw new Exception("No permission", ex);
        }

        var rulesCast = rules.Cast<FileSystemAccessRule>();
        if(rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Deny)
            || !rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Allow))
            throw new Exception("No permission");

        //Here I have permission, ole!

3voto

John Points 60

Aucun de ces fonctionné pour moi.. ils reviennent comme vrai, même quand ils ne sont pas. Le problème est, vous avez pour tester le disponible d'autorisation à contre-courant du processus des droits de l'utilisateur, ce tests pour la création de fichiers de droits, il suffit de changer le FileSystemRights clause "d'Écrire" pour tester l'accès en écriture..

/// <summary>
/// Test a directory for create file access permissions
/// </summary>
/// <param name="DirectoryPath">Full directory path</param>
/// <returns>State [bool]</returns>
public static bool DirectoryCanCreate(string DirectoryPath)
{
    if (string.IsNullOrEmpty(DirectoryPath)) return false;

    try
    {
        AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
        WindowsIdentity identity = WindowsIdentity.GetCurrent();

        foreach (FileSystemAccessRule rule in rules)
        {
            if (identity.Groups.Contains(rule.IdentityReference))
            {
                if ((FileSystemRights.CreateFiles & rule.FileSystemRights) == FileSystemRights.CreateFiles)
                {
                    if (rule.AccessControlType == AccessControlType.Allow)
                        return true;
                }
            }
        }
    }
    catch {}
    return false;
}

2voto

RockWorld Points 1014

Vous pouvez essayer de bloc de code suivant pour vérifier si le répertoire est d'avoir l'Accès en Écriture.

Il vérifie la FileSystemAccessRule.

           string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
           bool isWriteAccess = false;
           try
           {
              AuthorizationRuleCollection collection = Directory.GetAccessControl(directoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
              foreach (FileSystemAccessRule rule in collection)
              {
                 if (rule.AccessControlType == AccessControlType.Allow)
                 {
                    isWriteAccess = true;
                    break;
                 }
              }
           }
           catch (UnauthorizedAccessException ex)
           {
              isWriteAccess = false;
           }
           catch (Exception ex)
           {
              isWriteAccess = false;
           }
           if (!isWriteAccess)
           {
             //handle notifications                 
           }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X