2014-10-30 58 views
0

我有一個使用ASP.Net Web API 2並通過OWIN oAuth 2提供程序提供oAuth支持的項目。一切工作正常,但我試圖區分經過身份驗證的用戶和匿名用戶時遇到了問題。ASP.Net Web API 2授權時的不同內容

我可以很容易地提供[Authorize]和[AllowAnonymous]屬性,但都不完全符合我想要的。 [授權]將只允許授權用戶,[允許匿名]將允許任何人進行身份驗證或不授權。

就是我要找的行爲如下:

  • 用戶請求的端點沒有授權頭在他們的要求 - 在終端的內容的匿名版本返回
  • 用戶請求在其請求中帶有有效授權標頭的端點 - 返回端點內容的已登錄版本
  • 用戶請求帶有無效au的端點thorisation頭在他們的要求 - 服務器返回的401

狀態代碼,我可以建立一個自定義屬性,將做到這一點,但我不知道是否有一種方法可以做到這一點本身,而無需創建一個自定義屬性。

非常感謝您提供的任何幫助。

Richard。

我拿出UPDATE

一種選擇是創建AuthorizeAttribute的這樣的一個子類:

public class SuccessfulAuthorizationOrAnonymousAttribute : AuthorizeAttribute 
{ 
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     if(actionContext.RequestContext.Principal.Identity.IsAuthenticated) 
      return base.IsAuthorized(actionContext); 
     else 
     { 
      if (actionContext.Request.Headers.Authorization != null) 
      { 
       // If there's an authorization header, but there Principal.Identity.IsAuthenticated is false, then authentication must have failed 
       return false; 
      } 
      else 
      { 
       // There's no authorization header - therefore the user cannot have attempted to authenticate. A true anonymous request? 
       return true; 
      } 

     } 
    } 
} 

的邏輯是,如果用戶通過自帶這個屬性爲經過身份驗證,那麼我可以讓基類處理它們是否實際授權查看內容。

但是,如果他們通過未經身份驗證,那麼我可以檢查是否有請求中的授權標頭,如果有,那麼我認爲我可以推斷出身份驗證嘗試失敗。如果是這種情況,那麼我可以返回他們沒有權限訪問資源。

如果沒有授權標頭,那麼用戶沒有嘗試認證(我使用的API只支持承載認證 - 沒有別的),所以我很安全地將用戶視爲匿名。

從我的測試中,這種方法似乎表現得很好,儘管它的確有點像黑客。爲什麼我不應該這樣做,我看不到?

謝謝,

理查德。

+0

這是你的API相同的終點或不同的終點? – 2014-10-30 21:51:59

+0

它是相同的端點 - 基本上我現在可以根據用戶是否登錄返回不同的內容,但是當令牌不正確時,我需要端點返回401響應。順便說一句,我必須要感謝你 - 這是你在oAuth上的教程,可以讓我得到這麼多! – 2014-10-30 23:30:19

+0

歡迎您,很高興我的帖子很有用,現在將在答案部分回覆您的問題。 – 2014-10-31 07:12:52

回答

0

我不認爲你可以在同一時間接受匿名和認證用戶的單一端點執行此操作,我的建議是創建2個端點並將您的業務邏輯拉到私有方法,類似下面的應該工作爲你

[AllowAnonymous] 
[HttpPost] 
[Route("ActionForAnon")] 
public IHttpActionResult ActionForAnon() 
{ 
    return DoYourLogic(); 
} 

[Authorize] 
[HttpPost] 
[Route("ActionForAuth")] 
public IHttpActionResult ActionForAuth() 
{ 

    return DoYourLogic(); 

} 

private IHttpActionResult DoYourLogic() 
{ 
    var identity = User.Identity as ClaimsIdentity; 
    if (identity.IsAuthenticated) 
    { 
     //Your response for authenticated user 
    } 
    else { 
     //Your response for anonymous user 
    } 

    return Ok(); 
} 
+0

我當然可以做到這一點,但我寧願沒有不同的客戶端必須打電話的終端。我已經更新了這個問題以包含所提出的解決方案,所以現在的問題是有沒有什麼理由我不應該這樣做(我會說這對我來說就像是黑客,我相信還有更好的方式來做到這一點,但我不確定它究竟應該在什麼地方完成) – 2014-10-31 12:10:03

+0

好吧,如果你不想公開兩個端點,那麼你可以用你的方式,但我相信它可能無法工作,因爲一旦你重寫IzAuthorized屬性,[AllowAnonymous]屬性將不再起作用。 – 2014-10-31 17:58:21

+0

感謝您的警告 - 我不知道爲什麼它可能不起作用,但我會毫不猶豫地承認,我可能還不知道這兩個屬性是如何相關的。在我的情況下,一切似乎都在按照要求工作 - 需要授權工作的端點,不關心授權工作的端點,以及以不同方式處理經過驗證和未經驗證的請求的端點也可以工作,因此一切看起來都是按順序進行的。 – 2014-11-04 16:45:41