2014-10-20 53 views
81

我正在閱讀有關WebApi授權的一些​​資源(書籍和SO答案)。Asp.net WebApi中的自定義授權 - 多麼混亂?

假設我想添加自定義屬性,只允許特定用戶訪問:

案例#1

我見過的這種方法重寫OnAuthorization,這臺響應,如果事情是錯誤的

public class AllowOnlyCertainUsers : AuthorizeAttribute 
{ 
public override void OnAuthorization(HttpActionContext actionContext) 
    { 
    if (/*check if user OK or not*/) 
    { 
    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
    } 
    } 
} 

案例#2

但我也看到了這個類似的例子也覆蓋OnAuthorization但打電話來base

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
    base.OnAuthorization(actionContext); 

    // If not authorized at all, don't bother 

    if (actionContext.Response == null) 
    { 
     //... 
    } 
} 

然後,檢查 HttpActionContext.Response設置與否。如果它沒有設置,這意味着該請求被批准,用戶就可以了

案例#3

但我也看到了重寫IsAuthorized的這種做法:

public class AllowOnlyCertainUsers : AuthorizeAttribute 
{ 
protected override bool IsAuthorized(HttpActionContext context) 
    { 
    if (/*check if user OK or not*/) 
    { 
    return true;// or false 
    } 
    } 
} 

案例#4

然後我看到類似的例子之一,但調用base.IsAuthorized(上下文):

protected override bool IsAuthorized(HttpActionContext context) 
{ 
if (something1 && something2 && base.IsAuthorized(context)) //?? 
return true; 
return false; 
} 

一件事

最後多米尼克說here

你不應該重寫OnAuthorization - 因爲你會錯過[使用AllowAnonymous]處理。

問題

  • 1)我應該使用哪種方法:IsAuthorizedOnAuthorization? (或何時使用)

  • 2)什麼時候應該撥打base.IsAuthorized or base.OnAuthorization`?

  • 3)他們是如何構建它的?如果響應是空的,那麼一切都好?(案例#2)

NB

請注意,我使用(並希望使用)僅AuthorizeAttribute它已經從AuthorizationFilterAttribute

爲什麼繼承?

監守我在第一階段中:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

enter image description here

反正林通過延長授權的屬性要求。

+0

你需要重寫Authorize屬性嗎?你想達到什麼樣的用例?如果您需要允許某些用戶訪問,爲什麼不使用這樣的[Authorize(Users =「Admin」)]屬性? – 2014-10-20 13:08:44

+1

@TaiseerJoudeh例如,嘗試在10:00至12:00之間授權用戶(可配置)。你不能用簡單的角色和授權的attr來做到這一點。你必須制定你自己的邏輯 – 2014-10-20 13:11:21

回答

78

我應該使用哪些方法:IsAuthorized或OnAuthorization? (或 時使用的)

你會延長AuthorizationFilterAttribute如果您授權邏輯是不依賴於建立的身份和角色。對於用戶相關授權,您將擴展並使用AuthorizeAttribute。對於前一種情況,您將覆蓋OnAuthorization。對於後一種情況,您將覆蓋IsAuthorized。從這些屬性的源代碼中可以看出,如果您從AuthorizationFilterAttribute派生,則OnAuthorization被標記爲虛擬,以供您覆蓋。另一方面,IsAuthorized方法在AuthorizeAttribute中被標記爲虛擬。我相信這是一個很好的指向預期用途的指針。

什麼時候應該調用base.IsAuthorized或base.OnAuthorization?

這個問題的答案在於OO的工作原理。如果你重寫一個方法,你可以完全提供一個新的實現,或者回顧父級提供的實現並增強行爲。例如,以IsAuthorized(HttpActionContext)爲例。基類行爲是根據過濾器中指定的內容與建立的標識來檢查用戶/角色。比方說,你想做所有這些,但除此之外,你想檢查其他的東西,可能是基於請求頭或其他東西。在這種情況下,你可以提供這樣的覆蓋。

protected override bool IsAuthorized(HttpActionContext actionContext) 
{ 
    bool isAuthroized = base.IsAuthorized(actionContext); 
    // Here you look at the header and do your additional stuff based on actionContext 
    // and store the result in isRequestHeaderOk 
    // Then, you can combine the results 
    // return isAuthorized && isRequestHeaderOk; 
} 

對不起,但不明白你的Q3。順便說一句,授權過濾器已經存在很長時間了,人們會將它用於各種事情,有時也會出現錯誤。

還有一件事。終於有人在這裏說:你不應該重寫OnAuthorization - 因爲你會錯過 [AllowAnonymous]處理。

這個人說的是訪問控制的上帝 - 多米尼克。顯然這將是正確的。如果你看看OnAuthorization實施(以下複製),

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
    if (actionContext == null) 
    { 
     throw Error.ArgumentNull("actionContext"); 
    } 

    if (SkipAuthorization(actionContext)) 
    { 
     return; 
    } 

    if (!IsAuthorized(actionContext)) 
    { 
     HandleUnauthorizedRequest(actionContext); 
    } 
} 

調用SkipAuthorization是確保應用AllowAnonymous過濾器,也就是授權跳過的部分。如果你重寫這個方法,你就會失去這種行爲。實際上,如果您決定將您的授權基於用戶/角色,那麼您將決定從AuthorizeAttribute中派生出來。在那時只有正確的選項會覆蓋IsAuthorized而不是已經被覆蓋的OnAuthorization,儘管在技術上可以做到這一點。

PS。在ASP.NET Web API中,有另一個稱爲認證過濾器的過濾器。想法是,您使用它作爲授權的認證和授權過濾器,如名稱所示。但是,有很多這種邊界被淹沒的例子。許多authroization過濾器的例子會做某種認證。無論如何,如果你有時間並想多瞭解一點,請看看這個MSDN article。免責聲明:這是我寫的。

+0

再次感謝,但是如果我閱讀行,IsAuthenticated是由OnAuthirization calles,所以爲什麼不重寫OnAuthorization並調用base.OnAuthorization,然後檢查響應? – 2014-10-20 17:04:45

+0

你確定可以,如果那是你想要的。 – Badri 2014-10-20 17:14:05

+0

在我的第三個問題中,我的意思是:在運行基本函數(base.OnAuthorization)之後,例如,檢查它是否成功的唯一方法是檢查Response屬性?, ps示例來自您的書:-) – 2014-10-20 17:16:21

14

好的,我的建議是,假設您使用OAuth承載標記來保護您的Web API,並且您在發佈令牌時將allowedTime設置爲用戶的聲明,則執行以下操作。你可以閱讀更多關於token based authentication here

  1. 創建CustomAuthorizeAttribute從AuthorizationFilterAttribute
  2. 覆蓋方法OnAuthorizationAsync派生,並使用下面的示例代碼:

    public class CustomAuthorizeAttribute : AuthorizationFilterAttribute 
    { 
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) 
        { 
    
         var principal = actionContext.RequestContext.Principal as ClaimsPrincipal; 
    
         if (!principal.Identity.IsAuthenticated) 
         { 
          return Task.FromResult<object>(null); 
         } 
    
         var userName = principal.FindFirst(ClaimTypes.Name).Value; 
         var userAllowedTime = principal.FindFirst("userAllowedTime").Value; 
    
         if (currentTime != userAllowedTime) 
         { 
          actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla"); 
          return Task.FromResult<object>(null); 
         } 
    
         //User is Authorized, complete execution 
         return Task.FromResult<object>(null); 
    
        } 
    } 
    
  3. 在控制器
  4. 現在你用CustomAuthorize屬性來保護您的控制器使用這種授權邏輯。
+1

謝謝。但我目前正在使用繼承'AuthorizationFilterAttribute'的'AuthorizeAttribute',以及 - 也用於學習我特別詢問了我應該使用哪種方法,以及有關響應是否包含內容或不適合... – 2014-10-20 14:33:48

2

ASP.NET v5 Introduced a completely new Authorization System. 對於那些將要使用.NET 5的人,我建議進入Microsoft.AspNet.Authorization。

它幾乎包含了保留 System.Web.Http.AuthorizeSystem.Web.Mvc.Authorize以及其他較舊的身份驗證實現所造成的混亂。

它提供了動作類型(創建,讀取,更新,刪除),資源,角色,聲明,視圖,自定義需求的一個非常好的抽象,並允許構建自定義處理程序,結合上述任何。另外這些處理程序也可以組合使用。

在ASP.NET V5授權現在提供了簡單聲明的作用,其中授權在 要求和處理程序表達了 更豐富的基於策略的模型評估對 要求用戶索賠。命令式檢查可以基於簡單的策略或評估用戶身份和用戶嘗試訪問的資源的屬性的策略。

+8

很高興知道,但根本不回答問題。 – Zero3 2016-04-19 07:49:20