【问题标题】:ASP.NET Web API in Azure: Customize authentication filter to prevent brute force?Azure 中的 ASP.NET Web API:自定义身份验证过滤器以防止暴力破解?
【发布时间】:2014-12-05 21:09:27
【问题描述】:

我有一个来自 VS2013 SPA 模板 (web api 2.2) 的网站,它利用了 ASP.NET Identity 2.1,一切运行良好。我的控制器方法如下所示:

    [Authorize]
    public Api.Models.Widget Get(int widgetId)
    {
    var requestingUserId = Int32.Parse(Microsoft.AspNet.Identity.IdentityExtensions.GetUserId(User.Identity));
    ...

}

它按预期工作:

  • 未授权用户无权访问
  • 授权用户进入后,我可以获取他们的用户ID

但是我现在想修改应用程序以防止过多的 API 请求。我计划检查该特定用户 ID 是否在特定时间范围内发出了一定数量的请求。我正在寻找最佳地点的建议。

我不想在每个控制器中都重复这个逻辑,看起来动作过滤器可能是最好的地方。但是由于这需要读取用户 ID,而且我不确定过滤器的顺序是否得到保证,所以如果可能的话,派生已经被调用以进行授权的过滤器并添加我的额外逻辑也可能是有意义的。

我想知道是否有人可以举一个做类似事情的例子?似乎不是“授权”,而是在自定义身份验证过滤器中,我不确定如何将其结合在一起。

感谢您的任何建议...

【问题讨论】:

    标签: asp.net asp.net-web-api asp.net-identity asp.net-web-api2 asp.net-authorization


    【解决方案1】:

    有几个过滤器选项:

    授权过滤器 就是否进行安全决策 执行一个动作方法,例如执行身份验证或 验证请求的属性。

    例子:

    public class WebApiAuthorizeAttribute : AuthorizeAttribute 
    {
        public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
        {
            base.OnAuthorization(actionContext);
    
            Guid userId = new Guid(HttpContext.Current.User.Identity.GetUserId());
    
            // ...here your validation logic 
        }
    }
    

    动作过滤器 包装动作方法执行。这个过滤器 可以执行额外的处理,例如提供额外的数据给 action 方法,检查返回值,或取消执行 动作方法

    为了尽量减少对服务器的影响,您可以在用户浏览器中缓存任何 http get 请求一段预定义的时间,如果用户在该预定义时间内请求相同的 URL,则响应将从浏览器缓存中加载,而不是从服务器。 由于 Web API 没有 OutputCache 属性,您可以使用 this Output caching in ASP.NET Web API post as alternative 或者您可以为缓存实现自己的 Action 过滤器属性:

    public class CacheFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// Gets or sets the cache duration in seconds. The default is 10 seconds.
        /// </summary>
        /// <value>The cache duration in seconds.</value>
        public int Duration
        {
            get;
            set;
        }
    
        public CacheFilterAttribute()
        {
            Duration = 10;
        }
    
        public override void OnActionExecuted(FilterExecutedContext filterContext)
        {
            if (Duration <= 0) return;
    
            HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
            TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
    
            cache.SetCacheability(HttpCacheability.Public);
            cache.SetExpires(DateTime.Now.Add(cacheDuration));
            cache.SetMaxAge(cacheDuration);
            cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
        }
    }
    

    其他注意事项

    一旦用户对您的 web api 进行调用,您必须将 +1 添加到计数器,然后使用此计数器检查同一用户在某个时间范围内的大量调用。这里的问题是在哪里存储这个计数器。

    如果您将计数器存储在 SQL Server 等 RDBMS 中,则每个用户调用都会执行一次数据库访问。这可能会成为性能问题。这种存储应该尽可能轻。所以使用 NoSQL 数据库可能是一个不错的方法。

    【讨论】:

    • "这个存储应该尽可能的轻。所以使用 NoSQL 数据库可能是一个好方法。"是的,很好的电话。由于这是在 Azure 中,因此我计划为此使用 Azure 表存储。感谢您的帮助!
    • @BenjiFB 我同意这种细粒度的会话状态跟踪不是 SQL Server 的工作,但我不确定 Azure 表存储是否也适用。我的预感是,在这种情况下,Azure Redis 缓存的性能会提高一个数量级。我觉得这个节流计划正在变成一个小型项目,只是为了满足感知需求。请记住,真正的恶意用户可能会淹没您的系统并导致其挂起那些进程外会话频率检查,尤其是在未使用异步等待编码实践的情况下。
    【解决方案2】:

    我认为您正在关注的是一个过滤器,它将限制您的用户发出的请求,因此您应该检查 WebApiThrottle https://github.com/stefanprodan/WebApiThrottle

    这应该可以满足您的目标,或者您可以查看源代码以根据您的需要对其进行自定义

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-11
      • 2016-05-06
      • 2013-10-01
      • 2018-03-15
      • 2014-05-21
      • 2015-03-22
      • 2020-10-24
      • 2014-03-03
      相关资源
      最近更新 更多