简体   繁体   中英

Asp.net Core 2.2, Middleware doesn't always execute when moving between static html files

I have an asp.net core web application that has a directory of static files (all html/csv) right outside of wwwroot. I created a middleware to check that a user is authenticated before they can access those files. However, the middleware sometimes doesn't always execute when I go from one html file to another (either through url or href) within these static files. And even when I log out I can still sometimes access these files. I am also using Cookies Authentication Scheme and not Identity. This middle ware is based off of Scott Allen's tutorial https://odetocode.com/blogs/scott/archive/2015/10/06/authorization-policies-and-middleware-in-asp-net-5.aspx

I tried adding breakpoints within the middleware code, and I see that sometimes it doesn't trigger even though it is a new request.

   public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>()
                .AddDefaultUI(UIFramework.Bootstrap4)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddAuthentication( options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {

                    options.AccessDeniedPath = "/Home/Index";
                    options.LoginPath = "/Identity/Account/Login";
            });
            services.AddAuthorization(options =>
            {
                options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
            });

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {


            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();

            app.UseAuthentication();



            app.UseProtectFolder(new ProtectFolderOptions
            {
                Path = "/StaticFiles",
                PolicyName = "Authenticated",

            });



            app.UseStaticFiles();
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "Static_Files")),
                RequestPath = "/StaticFiles"
            });
            //app.UseStaticFiles(new StaticFileOptions
            //{
            //    FileProvider = new PhysicalFileProvider(


            //        Path.Combine(Directory.GetCurrentDirectory(), "StaticFiles")),
            //        RequestPath = "/StaticFiles"
            //});



            app.UseCookiePolicy();



            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

            });
        }

        private object RedirectResult()
        {
            throw new NotImplementedException();
        }
    }

    public class ProtectFolderOptions
    {
        public PathString Path { get; set; }
        public string PolicyName { get; set; }
    }
    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class ProtectFolderExtensions
    {
        public static IApplicationBuilder UseProtectFolder(this IApplicationBuilder builder, ProtectFolderOptions options)
        {
            return builder.UseMiddleware<ProtectFolder>(options);
        }
    }

    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class ProtectFolder
    {
        private readonly RequestDelegate _next;
        private readonly PathString _path;
        private readonly string _policyName;

        public ProtectFolder(RequestDelegate next,ProtectFolderOptions options)
        {
            _next = next;
            _path = options.Path;
            _policyName = options.PolicyName;
        }

        public async Task Invoke(HttpContext httpContext, IAuthorizationService authorizationService)
        {



            if (httpContext.Request.Path.StartsWithSegments(_path))
            {
                var authorized = await authorizationService.AuthorizeAsync(httpContext.User, null, _policyName);


                if (authorized.Succeeded == false)
                {
                    await httpContext.ChallengeAsync();
                    return;
                }
            }



            await _next(httpContext);
        }

The user should have no access to these files in the Static_Files directory unless they are signed in. This works. However, after I've signed out, I can still sometimes access these html files. After I've signed out the middleware sometimes doesn't trigger and I would be given access to the html files when I call a new request in the URL or move across the html files with their inner hrefs.

Your static files are probably being cached in the browser, hence, once they are accessed legitimately, they are cached and subsequent requests don't need to go to the server until the resource has expired.

You can disable caching of the files with something like this:-

app.UseStaticFiles(new StaticFileOptions()
{
    OnPrepareResponse = (context) =>
    {
        context.Context.Response.Headers["Cache-Control"] = "no-cache, no-store";
        context.Context.Response.Headers["Expires"] = "-1";
        context.Context.Response.Headers["Pragma"] = "no-cache";
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM