Список файлов, к которым у пользователя есть права на чтение (ASP.NET) - PullRequest
2 голосов
/ 05 февраля 2010

Я хочу перечислить все файлы в папке, к которой у пользователя есть доступ для чтения. Пользователь посещает веб-сайт и может использовать проверку подлинности с помощью форм для некоторых аспектов сайта (например, добавление ссылок и т. Д.), Но я хочу перечислить файлы в указанной папке, используя их учетные данные 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

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

Ответы [ 2 ]

2 голосов
/ 19 февраля 2010

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

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

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 (обычно сетевой службы).

1 голос
/ 05 февраля 2010

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

...