Asp.net在开发环境中"禁用"身份验证

fra*_*fra 16 asp.net-core

是否可以在不改变逻辑的情况下在asp.net核心应用程序中"禁用"身份验证?

我有一个.net网站,它使用外部身份服务器应用程序进行身份验证.无论如何,我希望能够在我开发它时模拟身份验证(ASPNETCORE_ENVIRONMENT =开发),对所有忽略授权属性的操作进行访问.

是否可以仅仅模拟服务集合中的某些服务?

Sim*_*per 45

在更新到 net core 3.1 时,mvcAllowAnonymousFilter不再为我们工作。我们发现有条件地添加自定义IAuthorizationHander是有条件地绕过身份验证的最简单方法。

例如。

/// <summary>
/// This authorisation handler will bypass all requirements
/// </summary>
public class AllowAnonymous : IAuthorizationHandler
{
    public Task HandleAsync(AuthorizationHandlerContext context)
    {
        foreach (IAuthorizationRequirement requirement in context.PendingRequirements.ToList())
            context.Succeed(requirement); //Simply pass all requirements
        
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Startup.ConfigureServices.

private readonly IWebHostEnvironment _env;
public Startup(IWebHostEnvironment env)
{
    _env = env;
}

public void ConfigureServices(IServiceCollection services)
{
  {...}

  //Allows auth to be bypassed
  if (_env.IsDevelopment())
    services.AddSingleton<IAuthorizationHandler, AllowAnonymous>();
}

Run Code Online (Sandbox Code Playgroud)

NoteAddAuthenticationAddAuthorization服务仍然按照 prod 代码进行注册和配置(这很好)。

为了让我们的单元测试绕过身份验证,我们添加了一个新的匿名测试库,其中包含一个启动类,该类在没有任何条件的情况下添加了这一行。好看又简单!

  • 这绝对有助于 3.1 升级。不确定这是否是一个已知问题? (2认同)
  • 无需使用 Linq 并在 context.PendingRequirements 上调用 .ToList(),因为它已经是 IEnumerable,并且可以通过 foreach 进行迭代而无需转换。 (2认同)

rox*_*ton 21

在 ASP.NET Core 3.x 及更高版本中,您可以通过使用扩展方法应用AllowAnonymousAttribute到您的端点来绕过开发环境中的授权。Startup.Configure()WithMetadata


示例 1.适用AllowAnonymousAttribute于控制器:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseEndpoints(endpoints =>
    {
        if (env.IsDevelopment())
            endpoints.MapControllers().WithMetadata(new AllowAnonymousAttribute());
        else
            endpoints.MapControllers();
    });
}
Run Code Online (Sandbox Code Playgroud)

请注意,这将适用AllowAnonymousAttribute所有控制器。


示例 2.应用于AllowAnonymousAttribute构建的端点MapGet()

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseEndpoints(endpoints =>
    {
        var hiEndpoint = endpoints
            .MapGet("/hi", async context => await context.Response.WriteAsync("Hello!"))
            .WithMetadata(new AuthorizeAttribute());
        
        if (env.IsDevelopment())
            hiEndpoint.WithMetadata(new AllowAnonymousAttribute());
    });
}
Run Code Online (Sandbox Code Playgroud)

细节

endpoints,它是 的一个实例IEndpointRouteBuilder,有多个Map扩展方法,如MapControllers()MapGet(...)返回IEndpointConventionBuilderWithMetadataIEndpointConventionBuilder这些endpoints.Map方法的扩展 ,可以调用这些方法的结果。

AllowAnonymousAttribute来自文档的描述:

指定应用此属性的类或方法不需要授权。

  • 谢谢,这就是我一直在寻找的:禁用 .NET Core 3.x 和 WebApi 开发环境的身份验证。所有其他解决方案都不适合我。 (2认同)

ozz*_*zzy 16

您可能要考虑的另一个解决方案是使用 IPolicyEvaluator。这意味着您可以保留所有现有的安全元素。

public class DisableAuthenticationPolicyEvaluator : IPolicyEvaluator
{
    public async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
    {
        // Always pass authentication.
        var authenticationTicket = new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), JwtBearerDefaults.AuthenticationScheme);
        return await Task.FromResult(AuthenticateResult.Success(authenticationTicket));
    }

    public async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
    {
        // Always pass authorization
        return await Task.FromResult(PolicyAuthorizationResult.Success());
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Startup.cs 中,确保它出现在 ConfigureServices 方法的顶部。例如。

    public void ConfigureServices(IServiceCollection services)
    {
        if (env.IsDevelopment())
        {
            // Disable authentication and authorization.
            services.TryAddSingleton<IPolicyEvaluator, DisableAuthenticationPolicyEvaluator>();
        }
        ...
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Core 3.1 并且希望使用 WebApplicationFactory,而不是 Startup.cs(并感谢下面的评论),您可以执行以下操作:

public class MyWebApplicationFactory : WebApplicationFactory<Program>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            // Disable Authentication.
            services.RemoveAll<IPolicyEvaluator>();
            services.AddSingleton<IPolicyEvaluator, DisableAuthenticationPolicyEvaluator>();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此处提供最佳解决方案,适用于 core 3.1。简单、优雅、可重复使用。 (3认同)
  • 我有另一个由产品“Startup”(使用 JWT)注入的“IPolicyEvaluator”,所以我需要在“AddSingleton”之前“services.RemoveAll&lt;IPolicyEvaluator&gt;();”。不使用 TryAddSingleton 是少了一个导入,无需尝试,正如我发现的那样,如果已经注册了一个,“TryAddSingleton”确实*不会添加单例* (2认同)

小智 15

我在illucIT博客上找到了解决这个问题的方法.

此代码必须有效:

if (env.IsDevelopment()) {
   services.AddMvc(opts =>
   {
      opts.Filters.Add(new AllowAnonymousFilter());
   });
} else {
   services.AddMvc();
}
Run Code Online (Sandbox Code Playgroud)

  • 这在最新的.net内核中不起作用,因为`IHostingEnvironment`没有传递给`ConfigureServices`。 (4认同)
  • @Dagrooms 你可以将 `IHostingEnvironment` 注入 `Startup` 构造函数并在 `ConfigureServices` 中使用它;) (3认同)
  • 是的,在扫描文档后发现,找到好的信息非常困难 (2认同)

Mic*_*iey 6

在没有更多详细信息的情况下给出详细答案是很棘手的,但我之前通过有条件地注册来实现这一点:

  • 外部认证中间件
  • 需要经过身份验证的请求的全局策略

它看起来像:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        Environment = env;
    }

    public IHostingEnvironment Environment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(x =>
        {
            if (!Environment.IsDevelopment())
            {
                var authenticatedUserPolicy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();

                x.Filters.Add(new AuthorizeFilter(authenticatedUserPolicy));
            }
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseStaticFiles();

        if (!Environment.IsDevelopment())
        {
            // Register external authentication middleware
        }

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

就我而言,授权过滤器是全局应用的,因此MVC应用程序的每个操作都需要经过身份验证的用户.

如果您有不同的要求 - [Authorize]某些操作的细粒度属性 - 那么您可以通过更改相关授权策略的构建方式来实现相同的结果.它们基本上根本不包含任何要求.

AuthorizationPolicy yourCustomPolicy = null;
if (Environment.IsDevelopment())
{
    yourCustomPolicy = new AuthorizationPolicyBuilder().Build();
}
else
{
    yourCustomPolicy = new AuthorizationPolicyBuilder()
        // chaining appropriate methods to suit your needs
        .Build();
}
Run Code Online (Sandbox Code Playgroud)


Cri*_*oni 5

在 ASP.NET Core 6 中,我们设法禁用授权,而无需更改生产代码中的任何其他部分,只需 Program.cs 中的以下逻辑:

if (!builder.Environment.IsDevelopment())
{
    app.MapControllers();
}
else
{
    app.MapControllers().AllowAnonymous();
}
Run Code Online (Sandbox Code Playgroud)