In MVC6 how can I block direct access to a folder in wwwroot?

二次信任 提交于 2019-12-04 05:59:40

Here's a sightly different approach, that uses an inline middleware to block unauthenticated requests for specific paths:

app.Use((context, next) => {
    // Ignore requests that don't point to static files.
    if (!context.Request.Path.StartsWithSegments("/app")) {
        return next();
    }

    // Don't return a 401 response if the user is already authenticated.
    if (context.User.Identities.Any(identity => identity.IsAuthenticated)) {
        return next();
    }

    // Stop processing the request and return a 401 response.
    context.Response.StatusCode = 401;
    return Task.FromResult(0);
});

Make sure to register it after your authentication middleware (or context.User won't be populated) and before the other middleware (in your case, before the static files middleware). You'll also have to make sure you're using automatic authentication (AutomaticAuthenticate = true). If not, you'll have to use the authentication API:

app.Use(async (context, next) => {
    // Ignore requests that don't point to static files.
    if (!context.Request.Path.StartsWithSegments("/app")) {
        await next();
        return;
    }

    // Don't return a 401 response if the user is already authenticated.
    var principal = await context.Authentication.AuthenticateAsync("Cookies");
    if (principal != null && principal.Identities.Any(identity => identity.IsAuthenticated)) {
        await next();
        return;
    }

    // Stop processing the request and trigger a challenge.
    await context.Authentication.ChallengeAsync("Cookies");
});

Note: if you want to prevent the cookies middleware from replacing the 401 response by a 302 redirect, here's how you can do:

When using Identity (in ConfigureServices):

services.AddIdentity<ApplicationUser, IdentityRole>(options => {
    options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents {
        OnValidatePrincipal = options.Cookies.ApplicationCookie.Events.ValidatePrincipal,
        OnRedirectToLogin = context => {
            // When the request doesn't correspond to a static files path,
            // simply apply a 302 status code to redirect the user agent.
            if (!context.Request.Path.StartsWithSegments("/app")) {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.FromResult(0);
        }
    };
});

When using the cookies middleware without Identity (in Configure):

app.UseCookieAuthentication(options => {
    options.Events = new CookieAuthenticationEvents {
        OnRedirectToLogin = context => {
            // When the request doesn't correspond to a static files path,
            // simply apply a 302 status code to redirect the user agent.
            if (!context.Request.Path.StartsWithSegments("/app")) {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.FromResult(0);
        }
    };
});

After additional research, it seems that the easiest way to accomplish what you want is to actually use the OnPrepareResponse StaticFileOption while configuring UseStaticFiles.

The following would be placed inside of Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    ILoggerFactory loggerFactory)
{
    app.UseStaticFiles(new StaticFileOptions()
    {
        OnPrepareResponse = s =>
        {
            if (s.Context.Request.Path.StartsWithSegments(new PathString("/app")) && 
               !s.Context.User.Identity.IsAuthenticated)
            {
                s.Context.Response.StatusCode = 401;
                s.Context.Response.Body = Stream.Null;
                s.Context.Response.ContentLength = 0;
            }
        }
    });
}

The above code will ONLY be run when executing a static file WITHIN wwwroot and specifically within any path that starts with the "/app" segment. If not authenticated, it rewrites the response so that the normal content is not delivered to the client, along with an appropriate status code.

For Prevent user from direct access to a folder, Please try this code

<security>
  <requestFiltering>
    <hiddenSegments>
      <add segment="folderName"/>
    </hiddenSegments>
  </requestFiltering>
</security>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!