如何使用基于声明的授权保护 asp.net core 2.1 中的静态文件夹 [英] How to protect static folder in asp.net core 2.1 using claims-based authorization

查看:28
本文介绍了如何使用基于声明的授权保护 asp.net core 2.1 中的静态文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 asp.net core 2.1 的小项目.我希望保护充满静态资产的文件夹.我尝试实现的是基于这篇文章 https://odetocode.com/blogs/scott/archive/2015/10/06/authorization-policies-and-middleware-in-asp-net-5.aspx

I have a small project which uses asp.net core 2.1. I wish to protect folder full of static assets. I tried to implement is based on this article https://odetocode.com/blogs/scott/archive/2015/10/06/authorization-policies-and-middleware-in-asp-net-5.aspx

我正在使用 Cookie 和基于声明的授权.所有应该检查授权的视图都可以正常工作......除了静态文件夹.当我检查 httpContext.User 时,它缺少所有预期的声明.

I am using cookies and claims-based authorization. All view which are supposed to check authorization work fine... except static folder. When I check httpContext.User it is missing all expected claims.

中间件:

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)
            {
                await httpContext.ChallengeAsync();
                return;
            }
        }

        await _next(httpContext);
    }
}

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddMvc()
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizePage("/Contact");
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
        services.AddAuthorization(options =>
        {
            options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
        });

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

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseCookiePolicy();
        app.UseProtectFolder(new ProtectFolderOptions
        {
            Path = "/Docs",
            PolicyName = "Authenticated"
        });
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Docs")),
            RequestPath = "/Docs",
        });

        app.UseAuthentication();
        app.UseMvc();
    }
}

登录非常简单.只需设置cookie,验证时

Login is very simple. Just set the cookie, when authenticate

public async Task<IActionResult> OnGetAsync(string returnUrl = null)
    {
        ReturnUrl = returnUrl;

        if (ModelState.IsValid)
        {
            var user = await AuthenticateUser("aaa");

            if (user == null)
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return Page();
            }

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.Email),
                new Claim("FullName", user.FullName),
                new Claim(ClaimTypes.Role, "Administrator"),
            };

            var claimsIdentity = new ClaimsIdentity(
                claims, CookieAuthenticationDefaults.AuthenticationScheme);

            var authProperties = new AuthenticationProperties
            {
            };

            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme, 
                new ClaimsPrincipal(claimsIdentity), 
                authProperties);

            _logger.LogInformation($"User {user.Email} logged in at {DateTime.UtcNow}.");

            return LocalRedirect(Url.GetLocalUrl(returnUrl));
        }
        return Page();
    }

    private async Task<ApplicationUser> AuthenticateUser(string token)
    {
        await Task.Delay(500);

        if (token == "aaa")
        {
            return new ApplicationUser()
            {
                Email = "aaa@gmail.com",
                FullName = "aaa"
            };
        }
        else
        {
            return null;
        }
    }

再来一次.它适用于除静态文件夹之外的所有需要​​身份验证的页面.我做错了什么?

Once again. It works for all pages which require authentication except static folder. What am I doing wrong?

推荐答案

    app.UseAuthentication(); //<-- this should go first

    app.UseProtectFolder(new ProtectFolderOptions
    {
        Path = "/Docs",
        PolicyName = "Authenticated"
    });

首先调用 UseStaticFiles() 将缩短静态文件的管道.因此不对静态文件进行身份验证.

Calling UseStaticFiles() first will short-cut the pipeline for static files. So no authentication are done on the static files.

有关 Startup.Configure order 的更多信息:

More info on Startup.Configure order here:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-2.1#order

这篇关于如何使用基于声明的授权保护 asp.net core 2.1 中的静态文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆