Asp.net web api 以编程方式将[AllowAnonymous]属性添加到所有my controller方法

Asp.net web api 以编程方式将[AllowAnonymous]属性添加到所有my controller方法,asp.net-web-api,authorization,Asp.net Web Api,Authorization,我有一个带有多个控制器的WebAPI2 REST api。我使用基于角色的身份验证。我在我所有的控制器和一些方法上设置了[Authorize]属性。但是,在DEV环境中,我想禁用身份验证。我希望可以在WebApiConfig中添加一些代码,例如: public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttri

我有一个带有多个控制器的WebAPI2 REST api。我使用基于角色的身份验证。我在我所有的控制器和一些方法上设置了[Authorize]属性。但是,在DEV环境中,我想禁用身份验证。我希望可以在
WebApiConfig
中添加一些代码,例如:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

        //==============================================
        // NOTE: disable all authentication in the DEV_ENVIRONMENT

        if (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1")
        {
            config.Filters.Add(new AllowAnonymousAttribute());
        }
    }
}
但是,这不会编译,因为

error CS1503: Argument 1: cannot convert from 
'System.Web.Http.AllowAnonymousAttribute' to 
'System.Web.Http.Filters.IFilter'

在运行时是否有办法关闭REST api中的所有身份验证?

我将分享几种方法。按照我的服务的工作方式,我们有一个基本的控制器类FooController,其中包含服务的所有逻辑。每个环境(请不要问!)我们有从FooController派生的DevFooController

Register
方法中,我们有一个非常类似的东西:

var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

/// api/{tenant}/{id}
config.Routes.MapHttpRoute(
      name: "RouteName",
      routeTemplate: "api/{tenant}/{id}",
      defaults: new { controller = controller, action = "actionName" });
这些属性将应用于相应的控制器

霍基?是的。作品也是的

我曾经使用的另一个系统是依赖注入。所有控制器均已注册。在每个请求中,注射器都有一些关于请求的有趣信息(dev/prod、flights、geo等),并且能够选择正确的混凝土控制器。这些类看起来很相似,但是FooController也实现了IFooController,并且多个注册的类都可以同时使用,而上面的示例中只有一个静态配置的路由可用

我更喜欢国际奥委会的做法,但当我现在支持的服务被写在白板上时,我不在场

我们以这种方式实现的一个显著特性是CORS支持。它在任何预生产端点上都不可用

最后,我们有一个ActionFilter在我们的几个方法上,它可能会像您所希望的那样工作。“允许匿名”逻辑在ActionFilter本身中。如果
您的条件为真
则过滤器将继续运行,而不验证任何身份。我们执行自己的AuthZ,但可以按照您描述的方式进行配置


希望这些建议中的一个能对您起作用。

我不会“删除”授权。假设您有一个客户,并且CustomerId是一个声明,那么您无法测试代码,因为声明丢失了。相反,我会选择添加一个用于开发目的的标识

这可能是一种黑客行为,但我的策略是添加一个过滤器,在其中设置当前用户,包括所需的角色:

在WebApiConfig.cs中添加过滤器:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SuppressDefaultHostAuthentication();

        // Add some logic here to determine the environment
        var isDevelopment = true;

        if (isDevelopment)
            config.Filters.Add(new AddIdentityFilter());

        // ...
    }
这样,您可以在开发时定义多个测试场景


对于asp.net core 3.0应用程序,这里有一个类似的方法。在启动中。配置:

if (env.IsDevelopment())
{
    // Custom authentication
    app.Use(async (context, next) =>
    {
        // Set claims for the test user.
        var claims = new[] { new Claim("role", "Admin"), new Claim("sub", "some guid") };
        var id = new ClaimsIdentity(claims, "DebugAuthorizationMiddleware", "name", "role");
        // Add the test user as Identity.
        context.User.AddIdentity(id);
        // User is now authenticated.
        await next.Invoke();
    });
}
else
{
    // use configured authentication
    app.UseAuthentication();
}
app.UseAuthorization();

令人惊叹的!这完全有效。我必须删除行
config.SuppressDefaultHostAuthentication()因为我没有使用OWIN。但显然没有必要。
if (env.IsDevelopment())
{
    // Custom authentication
    app.Use(async (context, next) =>
    {
        // Set claims for the test user.
        var claims = new[] { new Claim("role", "Admin"), new Claim("sub", "some guid") };
        var id = new ClaimsIdentity(claims, "DebugAuthorizationMiddleware", "name", "role");
        // Add the test user as Identity.
        context.User.AddIdentity(id);
        // User is now authenticated.
        await next.Invoke();
    });
}
else
{
    // use configured authentication
    app.UseAuthentication();
}
app.UseAuthorization();