代码之家  ›  专栏  ›  技术社区  ›  John Henckel

以编程方式将[AllowAnonymous]属性添加到我的所有控制器方法

  •  0
  • John Henckel  · 技术社区  · 6 年前

    我有一个带有多个控制器的webapi2restapi。我使用基于角色的身份验证。我把[授权]属性放在我所有的控制器和一些方法上。但是,在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'
    

    有没有办法在运行时关闭restapi中的所有身份验证?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Ruard van Elburg    5 年前

    我不会取消授权。假设您有一个客户,CustomerId是一个声明,那么您就不能测试代码,因为声明丢失了。相反,我会选择为开发目的添加一个标识。

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

    using System.Security.Principal;
    using System.Web;
    using System.Web.Http.Controllers;
    using System.Web.Http.Filters;
    
    public class AddIdentityFilter : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new[] { "Admin" });
            base.OnAuthorization(actionContext);
        }
    }
    

    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核心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();
    
        2
  •  1
  •   No Refunds No Returns    6 年前

    我将分享一些方法来做到这一点。按照我的服务工作方式,我们有一个基本的控制器类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本身中。如果 your condition is true 过滤器只是在不验证任何身份的情况下继续。我们执行自己的AuthZ,但可以像您描述的那样配置它。