开发者

List files user has read access to (ASP.NET)

开发者 https://www.devze.com 2022-12-19 02:03 出处:网络
I am wanting to list all the files in a folder that a user has read access to. The user visits the website and can use Forms Authentication for some aspects of the site (e.g. adding links etc), but I

I am wanting to list all the files in a folder that a user has read access to. The user visits the website and can use Forms Authentication for some aspects of the site (e.g. adding links etc), but I want to list files in a given folder using their Windows Credentials (since I have anonymous access turned off), hiding those they can't read.

However, when using Directory.GetFiles, it also includes files that can't be read (although the meta data (file size, creation date etc) can be read).

This is what I have:

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 FileInf开发者_StackOverflowo(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();
}

When I visit the page, I get UnauthorizedAccessException as soon as as I use GetAccessControl, even though it should be using the current user credentials. Taking the using off fails as the asp.net account does not have access to the folder. When FileSecurity is commented out, it lists all the files.

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

Any ideas of how I can do this, without resorting to trying to open each file and catching the exception that occurs?


Managed to fix it. When you deny Read on a file, it also denies read permissions, hence the UnauthorizedAccessException. So using try... catch ... looks like it is the only option.

It is possible to prevent the exception, if Read is denied and ReadPermissions is allowed (done under Advance settings). This handles both:

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

Now files can be listed in any directory (using impersonation) without giving the ASP.NET account (usually Network Service) access as well.


You probably need to set up Windows/Integrated Authentication in asp.net/IIS. http://msdn.microsoft.com/en-us/library/aa292114(VS.71).aspx

0

精彩评论

暂无评论...
验证码 换一张
取 消