3

我從VS2013 SPA模板(web api 2.2)中獲得了一個網站,它利用了ASP.NET Identity 2.1,並且一切運行良好。我的控制器方法是這樣的:Azure中的ASP.NET Web API:自定義身份驗證篩選器以防止暴力破解?

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

} 

它按預期工作:

  • 未經授權的用戶無權訪問
  • 授權的用戶獲取後,我能得到他們的用戶ID

但是我現在想修改應用程序來防止過多的API請求。我打算檢查一下特定的用戶ID是否在特定的時間段內發出了一定數量的請求。我正在尋找最佳地點的建議。

我不想在每個控制器中重複這個邏輯,而且它看起來像一個動作過濾器可能是最好的地方。但是,因爲這需要閱讀用戶標識,而且我不確定過濾器的順序是否得到保證,所以如果可能的話,也可以派生出已被調用授權並添加額外邏輯的過濾器。

我想知道是否有人可以舉一個類似的做法的例子嗎?它似乎不是「授權」,而是在自定義認證過濾器中,我不知道如何將它們結合在一起。

感謝您的任何建議...

回答

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 
    } 
} 

行動濾波器 裹操作方法執行。該過濾器 可以執行額外的處理,如提供額外的數據到 操作方法,檢查返回值,或取消的 執行的操作方法

爲了儘量減少您的服務器的影響,你可以緩存任何http在用戶瀏覽器中獲取請求預定義的時間,如果用戶在該預定義時間內請求相同的URL,則響應將從瀏覽器緩存而不是服務器加載。 作爲的OutputCache屬性是不可用的Web API,你可以使用this Output caching in ASP.NET Web API post as alternative或者你可以實現你自己的操作篩選器屬性緩存:一旦用戶進行對呼叫

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 db可能是一個好方法。

+0

「這個存儲應該儘可能輕,因此使用NoSQL db可能是一個好方法。」是的,很好的電話。由於這是在Azure中,我計劃爲此使用Azure表存儲。感謝您的有益迴應! – BenjiFB 2014-10-11 12:38:11

+0

@BenjiFB不客氣! – 2014-10-11 14:22:07

+0

@BenjiFB我同意,這種細粒度的會話狀態跟蹤不是SQL Server的工作,但我不確定Azure Table存儲是否是。我的直覺是,在這種情況下,Azure Redis緩存的性能會提高一個數量級。我覺得這個節流措施正在變成一個迷你項目,只是爲了一個需要的感覺。請記住,真正的惡意用戶可能會讓系統癱瘓,並導致它掛在進程會話頻率檢查之外,特別是如果不使用異步等待編碼實踐。 – camelCase 2014-12-18 01:09:27

4

我認爲你照顧是將油門由用戶製作,所以你應該檢查WebApiThrottle https://github.com/stefanprodan/WebApiThrottle

這應該做你的目標是做什麼,或者你可以檢查出的源代碼的請求的過濾器定製它四個您的需求

+0

+1爲好的解決方案。 – 2014-10-13 08:32:49

+0

很酷,謝謝! – BenjiFB 2014-10-22 14:21:48