Список файлов, к которым у пользователя есть доступ для чтения (ASP.NET)

Я хочу перечислить все файлы в папке, к которым у пользователя есть доступ для чтения. Пользователь посещает веб-сайт и может использовать проверку подлинности с помощью форм для некоторых аспектов сайта (например, добавления ссылок и т. д.), но я хочу перечислить файлы в данной папке, используя свои учетные данные Windows (поскольку у меня отключен анонимный доступ), скрывая те, которые они не могу читать.

Однако при использовании Directory.GetFiles он также включает файлы, которые нельзя прочитать (хотя метаданные (размер файла, дата создания и т. д.) могут быть прочитаны).

Вот что у меня есть:

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

Когда я посещаю страницу, я получаю UnauthorizedAccessException, как только я использую GetAccessControl, даже если он должен использовать учетные данные текущего пользователя. Отключить using не удается, поскольку учетная запись asp.net не имеет доступа к папке. Когда FileSecurity закомментирован, он перечисляет все файлы.

Трассировки стека:

[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

Любые идеи о том, как я могу это сделать, не прибегая к попытке открыть каждый файл и поймать возникающее исключение?


person SamWM    schedule 05.02.2010    source источник


Ответы (2)


Удалось исправить. Когда вы запрещаете чтение файла, он также запрещает права на чтение, поэтому UnauthorizedAccessException. Так что использование try... catch ... похоже, что это единственный вариант.

Исключение можно предотвратить, если чтение запрещено, а разрешения на чтение разрешены (сделано в дополнительных настройках). Это обрабатывает оба:

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

Теперь файлы могут быть перечислены в любом каталоге (используя олицетворение) без предоставления доступа к учетной записи ASP.NET (обычно сетевой службе).

person SamWM    schedule 19.02.2010
comment
Ненавижу придираться... но почему вы используете goto и ярлык? просто прервите или продолжите по мере необходимости. - person Justin Drury; 19.02.2010
comment
Пытался сломать, но он только ломает FileAccessRule foreach ... хотел выйти из него и перейти к следующему файлу. Хотя я полагаю, что можно было бы использовать логическое значение... Неудобно ли использовать метку, и если да, то почему? - person SamWM; 19.02.2010
comment
Goto отлично подходит для выхода из вложенных циклов. Это упрощает логику и повышает производительность во многих случаях, избегая ненужных условных разрывов на каждом уровне цикла. - person Triynko; 28.06.2011

Вероятно, вам нужно настроить Windows/Integrated Authentication в asp.net/IIS. http://msdn.microsoft.com/en-us/library/aa292114(VS.71).aspx

person Community    schedule 05.02.2010
comment
Сайт использует встроенную аутентификацию, и тот факт, что он может получить список файлов, показывает, что это так (в противном случае будет исключение, отличное от того, которое я получаю). Ошибка возникает при попытке получить правила доступа к файлу. - person SamWM; 08.02.2010