2013-03-31 64 views
7

我正在使用ASP.NET Web API。我真的很喜歡添加屬性來指定訪問權限級別這樣的API控制器的能力:如何使ASP.NET Web API適當地響應403或401?

[Authorize] 
public IEnumerable<Activity> Get() 

到目前爲止好,但是當我使用角色的概念打散。

[Authorize(Roles = "Manager")] 
public IEnumerable<Activity> Get() 

我的用戶可能登錄到系統而回,然後在某個時候,他們打一種資源,是「禁」到他們。用戶嘗試重新登錄沒有任何意義。由於其合法帳戶無法訪問該網址。但是目前他們得到401(未經授權)而不是403(禁止),就好像他們使用錯誤的帳戶登錄一樣。但用戶只有一個帳戶,並且用戶不希望用戶請求屬於他人的帳戶。

有沒有其他人處理過這個問題?有誰知道如何解決這一問題?我非常樂意編寫代碼來解決這個問題,但是我目前處於一個無法開始的狀態。

回答

0

你可以做的是創建一個自定義Authorize attribute,然後處理 AuthorizeCore,並在後者,您可以發送您preffer任何響應

OnAuthorizationFailed一個look here

+0

修改AuthorizeAttribue就是答案。因爲我使用的是WebAPI,所以這個特殊的例子是修改System.Web.Mvc而不是System.Web.Http。 –

+0

我以爲你想做一個自定義屬性發回你喜歡的Http狀態代碼 –

+0

這就是我所做的,我從System.Web.Http.AuthorizeAtribute繼承。不是從System.Web.Mvc.AuthorizeAtribute這是你指出的文章引用。 –

1

我做了一些調查,我爲我編寫了一個解決方案。我在System.Web.Mvc上找到兩個不同的Authorize屬性,而在System.Web.Http中找到第二個。第一個適用於常規的MVC4應用程序,第二個適用於MVC4的WebAPI部分,用於Web服務(包括RESTful接口)。所以我用了第二個。

我決定看看codeplex上的Authorize Attribute Source代碼。而且我發現這一點:

protected virtual bool IsAuthorized(HttpActionContext actionContext) 
    { 
     if (actionContext == null) 
     { 
      throw Error.ArgumentNull("actionContext"); 
     } 

     IPrincipal user = Thread.CurrentPrincipal; 
     if (user == null || !user.Identity.IsAuthenticated) 
     { 
      return false; 
     } 

     if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) 
     { 
      return false; 
     } 

     if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) 
     { 
      return false; 
     } 

     return true; 
    } 

這是很容易看到的身份驗證和訪問是由一個事實,即它們都具有返回false同樣的效果混爲一談。

這是我寫的new AuthorizeAttribute當用戶或角色不匹配時返回403。這樣你可以避免在本地登錄窗口。它包含以下代碼。

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

     if (!IsAllowed(actionContext)) 
     { 
      HandleForbiddenRequest(actionContext); 
     } 
23

閱讀Parv的建議下,我創建了一個名爲[WebApiAuthorize]以下自定義過濾器。

關鍵是HandleUnauthorizedRequest()方法。當代碼在此方法內執行時,這是因爲用戶未經授權「出於某種原因」......所以現在我們只是確定「爲什麼」......然後:

  1. 調用基本方法使用默認行爲(返回401)......或者......
  2. 回到我們自己的反應有403

正如你所看到的,它會返回403在適當的時候(身份驗證,而不是授權) 。

public class WebApiAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(HttpActionContext ctx) 
    { 
     if (!ctx.RequestContext.Principal.Identity.IsAuthenticated) 
      base.HandleUnauthorizedRequest(ctx); 
     else 
     { 
      // Authenticated, but not AUTHORIZED. Return 403 instead! 
      ctx.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden); 
     } 
    } 
} 

要使用,只是把定製過濾器控制器或動作這樣的.....

[WebApiAuthorize(Roles = "YourRoleA,YourRoleB")] 
public class AdminController : ApiController 
{ 
    public List<Admin> GetAdmins() 
    { 
     ... 
    } 
} 
+0

稍有改進之後正在發送的自定義代碼。您應該檢查Principal或Identity是否爲null,否則,如果請求未提供憑據,則可能會得到NullReferenceException。[受保護的bool IsAuthenticated(HttpActionContext ctx) var principal = ctx.RequestContext.Principal; return principal!= null && principal.Identity!= null && principal.Identity.IsAuthenticated; }' – Jehof