首页 > 解决方案 > Asp.net core,调试时绕过授权

问题描述

我有一个测试网站,它[AuthorizeAttribute]在整个控制器级别使用 aspnetCore,以确保只有经过身份验证的用户才能访问该网站。

当我们调试和测试新功能时,我们必须经常注释掉每个控制器中的属性,我知道这很容易忘记并且可能有一天会被合并。

我们在检查之前是否附加了调试器方面取得了很大的成功......我想知道我应该指定哪个 AuthenticationScheme 以允许匿名,只有在调试时。

我扩展了基础 AuthorizeAttribute,所以我有一个简单的地方可以在一些代码中填充。

public class MyAppAuthorizeAttribute : AuthorizeAttribute
    {
        public MyAppAuthorizeAttribute()
            : base(Policies.MyAppAuthorize)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.WriteLine("Skipping auth for debug");        //we hit this line but...
                this.AuthenticationSchemes = AllowAnonymousAttribute //this setting does not work
            }
            else
            {
                this.AuthenticationSchemes = "IntegratedWindowsAuthentication";
            }
            
        }
    }

标签: asp.net-coreauthorize

解决方案


在某些情况下,您可能需要对用户进行身份验证,但代码中并未实际引用您的要求(例如:代码不访问有关当前身份的任何信息,尤其是与用户的业务模型相关的信息)。因此,我假设您已经意识到这一点,因为以下内容只是简单地删除了在开发环境中运行代码时检查经过身份验证的用户的要求。还有另一种自动登录虚拟用户的方法,在某些情况下可能会更好。

这是第一个解决方案,它只配置一个不包含的默认策略DenyAnonymousAuthorizationRequirement(这是默认策略中包含的唯一要求)。这意味着如果您在某处使用了多个策略(带有AuthorizeAttribute),则只有默认值将被忽略(在调试时)。第二种解决方案(稍后显示)可能更适合这种情况。

//inject IHostingEnvironment in the Startup constructor
public Startup(IConfiguration configuration, IHostingEnvironment env){
   HostingEnvironment = env;
}
public IHostingEnvironment HostingEnvironment { get; }

//in the ConfigureServices method in Startup.cs
services.AddAuthorization(o => {
    if (HostingEnvironment.IsDevelopment()){
       o.DefaultPolicy = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme)
                         //there should be at least 1 requirement
                         //here we add a simple always-passed assertion
                         .RequireAssertion(e => true).Build();
    }         
    //...
});

我们需要使用IHostingEnvironment(在 .net core 2.2 中,自 3.0 以来我们有 2 个替代方案IWebHostEnvironmentIHostEnvironment),因此我们将其注入Startup构造函数并将其存储在只读属性中(如上所示)。还有另一种方法是尝试ASPNETCORE_ENVIRONMENT像这样直接获取变量:

var isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";

这是您使用自定义全局IAsyncAuthorizationFilter自动登录虚拟用户的第二个解决方案(因此它始终对所有请求进行身份验证)。

public class AllowAnonymousFilterAttribute : Attribute, IAsyncAuthorizationFilter
{
    readonly IHostingEnvironment _hostingEnvironment;
    public AllowAnonymousFilterAttribute(IHostingEnvironment env){
       _hostingEnvironment = env;
    }
    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        if (_hostingEnvironment.IsDevelopment() && !context.HttpContext.User.Identity.IsAuthenticated)
        {
            //prepare a dummy user to auto sign-in
            HttpContext.User = new ClaimsPrincipal(new[] {
                new ClaimsIdentity(new []{ new Claim(ClaimTypes.NameIdentifier,"admin")},
                                   CookieAuthenticationDefaults.AuthenticationScheme)
            });
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, 
                                          HttpContext.User);
        }
    }
}

全局注册过滤器,这里我写代码.net core 2.2

services.AddMvc(o => {
     //register the filter only for development (should be debugging)
     if (HostingEnvironment.IsDevelopment()){
       o.Filters.Add<AllowAnonymousFilterAttribute>();
     }
     //...
});

我敢肯定还有其他一些解决方案,但是我在这里介绍的内容相当简单,并且足以满足您的目的。

P/S:我上面介绍的第一个解决方案适用于.net core 2.2(实际上我目前无法访问更新版本的.net core,很遗憾)。对于较新的版本,Authorization中间件是独立的,因此您可能只是不像另一个答案所建议的那样.UseAuthorization()在方法中调用中间件Configure


推荐阅读