C# اختبار ما إذا كان المستخدم لديه حق الوصول إلى مجلد

StackOverflow https://stackoverflow.com/questions/1410127

  •  05-07-2019
  •  | 
  •  

سؤال

أحتاج إلى اختبار ما إذا كان يمكن للمستخدم الكتابة إلى مجلد قبل في الواقع محاولة القيام بذلك.

لقد نفذت الطريقة التالية (في C# 2.0) الذي يحاول استرداد الأمن أذونات المجلد باستخدام الدليل.GetAccessControl() الأسلوب.

private bool hasWriteAccessToFolder(string folderPath)
{
    try
    {
        // Attempt to get a list of security permissions from the folder. 
        // This will raise an exception if the path is read only or do not have access to view the permissions. 
        System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return false;
    }
}

عندما كنت أبحث كيفية اختبار الكتابة شيء مثل هذا جاء يبدو معقدا جدا في الواقع اختبار الأذونات في ويندوز.أنا قلقة من أن أنا الإفراط في تبسيط الأمور أن هذه الطريقة ليست قوية, على الرغم من أنه لا يبدو أن العمل.

سوف بلدي طريقة لاختبار ما إذا كان المستخدم لديه حق الوصول للكتابة العمل بشكل صحيح ؟

هل كانت مفيدة؟

المحلول

وهذه طريقة صحيحة تماما للتأكد من الوصول إلى المجلد في C #. المكان الوحيد الذي يمكن أن تسقط وإذا كنت بحاجة إلى استدعاء هذا في حلقة ضيقة حيث النفقات العامة استثناء <م> قد يكون مشكلة.

وكانت هناك مماثلة <ل أ href = "https://stackoverflow.com/questions/130617/how-do-you-check-for-permissions-to-write-to-a-directory-or-file"> الأسئلة طلب في وقت سابق.

نصائح أخرى

وأنا أقدر أن هذا هو قليلا في وقت متأخر من اليوم لهذا المنصب، ولكن قد تجد هذا الشيء من التعليمات البرمجية مفيدة.

string path = @"c:\temp";
string NtAccountName = @"MyDomain\MyUserOrGroup";

DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All);
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

//Go through the rules returned from the DirectorySecurity
foreach (AuthorizationRule rule in rules)
{
    //If we find one that matches the identity we are looking for
    if (rule.IdentityReference.Value.Equals(NtAccountName,StringComparison.CurrentCultureIgnoreCase))
    {
        var filesystemAccessRule = (FileSystemAccessRule)rule;

        //Cast to a FileSystemAccessRule to check for access rights
        if ((filesystemAccessRule.FileSystemRights & FileSystemRights.WriteData)>0 && filesystemAccessRule.AccessControlType != AccessControlType.Deny)
        {
            Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path));
        }
        else
        {
            Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path));
        }
    }
}

Console.ReadLine();

وإسقاط ذلك في التطبيق وحدة التحكم ومعرفة ما اذا كان يفعل ما تحتاجه.

public bool IsDirectoryWritable(string dirPath, bool throwIfFails = false)
{
    try
    {
        using (FileStream fs = File.Create(
            Path.Combine(
                dirPath, 
                Path.GetRandomFileName()
            ), 
            1,
            FileOptions.DeleteOnClose)
        )
        { }
        return true;
    }
    catch
    {
        if (throwIfFails)
            throw;
        else
            return false;
    }
}

وحاولت أكثر من هذه، ولكنها تعطي ايجابيات كاذبة، كل لنفس السبب .. لا يكفي لاختبار الدليل لإذن المتاحة، لديك للتأكد من أن قاموا بتسجيل الدخول هو عضو في مجموعة الذي لديه هذا الإذن. للقيام بذلك يمكنك الحصول على هوية المستخدمين، ومعرفة ما اذا كان هو عضوا في المجموعة التي تحتوي على FileSystemAccessRule IdentityReference. لقد جربت هذا، يعمل لا تشوبه شائبة ..

    /// <summary>
    /// Test a directory for create file access permissions
    /// </summary>
    /// <param name="DirectoryPath">Full path to directory </param>
    /// <param name="AccessRight">File System right tested</param>
    /// <returns>State [bool]</returns>
    public static bool DirectoryHasPermission(string DirectoryPath, FileSystemRights AccessRight)
    {
        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 ((AccessRight & rule.FileSystemRights) == AccessRight)
                    {
                        if (rule.AccessControlType == AccessControlType.Allow)
                            return true;
                    }
                }
            }
        }
        catch { }
        return false;
    }

وعلى سبيل المثال لجميع المستخدمين (مدمج \ المستخدمين)، هذا الأسلوب يعمل بشكل جيد - التمتع

public static bool HasFolderWritePermission(string destDir)
{
   if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false;
   try
   {
      DirectorySecurity security = Directory.GetAccessControl(destDir);
      SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
      foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
      {
          if(rule.IdentityReference == users)
          {
             FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
             if(rights.AccessControlType == AccessControlType.Allow)
             {
                    if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
             }
          }
       }
       return false;
    }
    catch
    {
        return false;
    }
}

وIMHO وسيلة يمكن الاعتماد عليها بنسبة 100٪ الوحيدة لاختبار ما اذا كان يمكنك إرسال بريد إلى دليل هو أن يكتب في الواقع لأنه في نهاية المطاف تصفية الاستثناءات.

وجرب هذا:

try
{
    DirectoryInfo di = new DirectoryInfo(path);
    DirectorySecurity acl = di.GetAccessControl();
    AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

    WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(currentUser);
    foreach (AuthorizationRule rule in rules)
    {
        FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
        if (fsAccessRule == null)
            continue;

        if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
        {
            NTAccount ntAccount = rule.IdentityReference as NTAccount;
            if (ntAccount == null)
            {
                continue;
            }

            if (principal.IsInRole(ntAccount.Value))
            {
                Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value);
                continue;
            }
            Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value);                        
        }
    }
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("does not have write access");
}

والتعليمات البرمجية يحصل على DirectorySecurity لدليل معين، ويتعامل مع استثناء (بسبب عدم وجود الخاص بك الوصول إلى المعلومات الأمنية) بشكل صحيح. ومع ذلك، في عينتك كنت لا فعلا استجواب الكائن عاد لمعرفة ما يسمح الوصول - وأعتقد أنك تحتاج إلى إضافة هذا في

وهنا هو نسخة معدلة من CsabaS في الإجابة ، التي تمثل قواعد الوصول صريحة تحرم. وظيفة تذهب من خلال جميع FileSystemAccessRules للدليل، ويتحقق إذا كان المستخدم الحالي في الدور الذي لديه حق الوصول إلى دليل. إذا لم يتم العثور على مثل هذه الأدوار أو المستخدم في دور مع وصول مرفوض، تقوم الدالة بإرجاع كاذبة. للتحقق قراءة حقوق، وتمرير FileSystemRights.Read إلى وظيفة. حقوق الكتابة، وتمرير FileSystemRights.Write. إذا كنت تريد أن تحقق حقوق المستخدم التعسفي وليس التيار واحد، واستبدال currentUser WindowsIdentity لWindowsIdentity المطلوب. أنصح أيضا ضد الاعتماد على وظائف مثل هذا لتحديد ما إذا كان يمكن للمستخدم استخدام بأمان الدليل. هذا الإجابة يفسر تماما لماذا.

    public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights)
    {
        var isInRoleWithAccess = false;

        try
        {
            var di = new DirectoryInfo(path);
            var acl = di.GetAccessControl();
            var rules = acl.GetAccessRules(true, true, typeof(NTAccount));

            var currentUser = WindowsIdentity.GetCurrent();
            var principal = new WindowsPrincipal(currentUser);
            foreach (AuthorizationRule rule in rules)
            {
                var fsAccessRule = rule as FileSystemAccessRule;
                if (fsAccessRule == null)
                    continue;

                if ((fsAccessRule.FileSystemRights & accessRights) > 0)
                {
                    var ntAccount = rule.IdentityReference as NTAccount;
                    if (ntAccount == null)
                        continue;

                    if (principal.IsInRole(ntAccount.Value))
                    {
                        if (fsAccessRule.AccessControlType == AccessControlType.Deny)
                            return false;
                        isInRoleWithAccess = true;
                    }
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
        return isInRoleWithAccess;
    }

ولقد استخدمت نفس الوظيفة لفحص إذا hasWriteAccess الملف:

    private static bool HasWriteAccessToFile(string filePath)
    {
        try
        {
            // Attempt to get a list of security permissions from the file. 
            // This will raise an exception if the path is read only or do not have access to view the permissions. 
            File.GetAccessControl(filePath);
            return true;
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
    }

ويمكنك محاولة التالية كتلة التعليمات البرمجية للتحقق مما إذا الدليل هو وجود الوصول للكتابة. فإنه يتحقق 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 
}

لديك شرط سباق المحتملة في التعليمات البرمجية - ماذا يحدث إذا كان المستخدم لديه أذونات الكتابة إلى المجلد عند التدقيق، ولكن قبل المستخدم يكتب في الواقع إلى المجلد يتم سحب هذا التصريح؟ فإن الكتابة بطرح استثناء والتي سوف تحتاج لالتقاط والتعامل معها. لذا فإن الفحص الأولي لا معنى لها. بالاضافة الى انك قد لا مجرد الكتابة والتعامل مع أي استثناءات. هذا هو نمط قياسي لموقفك.

http://www.codeproject.com/KB/files/UserFileAccessRights.aspx

والدرجة مفيدة جدا، تحقق من وجود نسخة محسنة في رسائل رفع الصوت عاليا.

الحلول المذكورة أعلاه هي جيدة و لكن بالنسبة لي أجد هذا كود بسيط وعملي.مجرد إنشاء ملف مؤقت.إذا كان يتم إنشاء ملف ، يعني أن المستخدم لديه حق الوصول للكتابة.

        public static bool HasWritePermission(string tempfilepath)
        {
            try
            {
                System.IO.File.Create(tempfilepath + "temp.txt").Close();
                System.IO.File.Delete(tempfilepath + "temp.txt");
            }
            catch (System.UnauthorizedAccessException ex)
            {

                return false;
            }

            return true;
        }

وببساطة محاولة الوصول إلى الملف في السؤال ليست بالضرورة كافية. سيتم تشغيل اختبار مع أذونات المستخدم تشغيل البرنامج - وهي ليست بالضرورة أذونات المستخدم الذي تريد اختباره ضد

وأنا أتفق مع الرماد، وينبغي أن يكون على ما يرام. بدلا من ذلك يمكنك استخدام CAS التعريفي وفعلا منع برنامج من التشغيل في المقام الأول إذا لم يكن لديك الوصول.

وأعتقد أن بعض الميزات CAS قد لا تكون موجودة في C # 4.0 من ما سمعت، ولست متأكدا إذا كان هذا قد يكون مشكلة أم لا.

لم أستطع الحصول على GetAccessControl () لرمي استثناء على ويندوز 7 على النحو الموصى به في الإجابة المقبولة.

وانتهى بي الأمر باستخدام تباين الجواب في المعيار الخاص :

        try
        {
            bool writeable = false;
            WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            DirectorySecurity security = Directory.GetAccessControl(pstrPath);
            AuthorizationRuleCollection authRules = security.GetAccessRules(true, true, typeof(SecurityIdentifier));

            foreach (FileSystemAccessRule accessRule in authRules)
            {

                if (principal.IsInRole(accessRule.IdentityReference as SecurityIdentifier))
                {
                    if ((FileSystemRights.WriteData & accessRule.FileSystemRights) == FileSystemRights.WriteData)
                    {
                        if (accessRule.AccessControlType == AccessControlType.Allow)
                        {
                            writeable = true;
                        }
                        else if (accessRule.AccessControlType == AccessControlType.Deny)
                        {
                            //Deny usually overrides any Allow
                            return false;
                        }

                    } 
                }
            }
            return writeable;
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }

وآمل أن يساعد هذا.

وأنا واجهت نفس المشكلة: كيفية التحقق ما اذا كان يمكنني القراءة / الكتابة في دليل معين. انتهى بي الأمر مع الحل السهل ... في الواقع اختباره. وإنني هنا بسيطة على الرغم من حل فعال.

 class Program
{

    /// <summary>
    /// Tests if can read files and if any are present
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canRead(string dirPath)
    {
        try
        {
            IEnumerable<string> files = Directory.EnumerateFiles(dirPath);
            if (files.Count().Equals(0))
                return new genericResponse() { status = true, idMsg = genericResponseType.NothingToRead };

            return new genericResponse() { status = true, idMsg = genericResponseType.OK };
        }
        catch (DirectoryNotFoundException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.ItemNotFound };

        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotRead };

        }

    }

    /// <summary>
    /// Tests if can wirte both files or Directory
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canWrite(string dirPath)
    {

        try
        {
            string testDir = "__TESTDIR__";
            Directory.CreateDirectory(string.Join("/", dirPath, testDir));

            Directory.Delete(string.Join("/", dirPath, testDir));


            string testFile = "__TESTFILE__.txt";
            try
            {
                TextWriter tw = new StreamWriter(string.Join("/", dirPath, testFile), false);
                tw.WriteLine(testFile);
                tw.Close();
                File.Delete(string.Join("/", dirPath, testFile));

                return new genericResponse() { status = true, idMsg = genericResponseType.OK };
            }
            catch (UnauthorizedAccessException ex)
            {

                return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteFile };

            }


        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteDir };

        }
    }


}

public class genericResponse
{

    public bool status { get; set; }
    public genericResponseType idMsg { get; set; }
    public string msg { get; set; }

}

public enum genericResponseType
{

    NothingToRead = 1,
    OK = 0,
    CannotRead = -1,
    CannotWriteDir = -2,
    CannotWriteFile = -3,
    ItemNotFound = -4

}

ونأمل أن يساعد!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top