2016-04-11 42 views
1

控制器上的Asp.net MVC5和WebApi2擁有Authorize屬性,可以讓您過濾角色。例如:如果用戶的角色不正確,Asp.net mv5 403或401代碼

[Authorize(Roles="HomePageUser")] 
public ActionResult Home(){ 
    return View(); 
} 

但這發出401狀態代碼,如果用戶進行身份驗證,但不正確的角色。我的問題很簡單:這是最好的方法,還是我應該編寫一個過濾器,如果它們通過身份驗證但發生錯誤角色,則會發送403

要明白爲什麼這是一個問題,請考慮:不在角色HomePageUser中的用戶登錄並嘗試訪問Home頁面。 Authorize過濾器會發出一個401代碼,然後Owin上下文會攔截並轉換爲302重定向到登錄頁面。但是,用戶實際上已登錄,並且沒有任何登錄可以糾正用戶身份缺少查看頁面權限的事實。

實際上,這一切都意味着對用戶感到沮喪,因爲自動重定向從來沒有給他們提供關於他們爲什麼看不到頁面的任何信息 - 他們很可能認爲他們輸入的密碼不正確。

在我看來,關鍵故障這裏就是Authorize過濾撒謊 - 用戶是不能擅自但禁止,它應該發出一個403

這是我心目中的代碼來解決這個。對於MVC操作:

using System.Web.Mvc; 

public class AuthorizeOrForbidAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      filterContext.Result = new HttpStatusCodeResult(403); 
     } 
     else 
     { 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 
} 

,併爲Web API操作:

using System.Web.Http; 
using System.Diagnostics.CodeAnalysis; 
using System.Diagnostics.Contracts; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Security.Principal; 
using System.Web.Http.Controllers; 
using System.Web.Http.Filters; 
using System.Web.Http.Properties; 

public class AuthorizeOrForbidAttribute: AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     if (actionContext.RequestContext.Principal.Identity.IsAuthenticated) 
     { 
      actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, actionContext.RequestContext.Principal.Identity.Name+" does not have permissions for this request."); 
     } 
     else 
     { 
      actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Authorization has been denied for this request."); 
     } 
    } 
} 

從那裏,它是很容易將這些狀態代碼重新定向到具體取決於您希望用戶看到相應的錯誤頁面。

這是一個很好的方法嗎?我很擔心,因爲我想知道微軟是否有一個很好的理由並沒有做到這一點。

+0

這似乎是正確的方式,因爲默認情況下Authorize屬性的行爲與您描述的一樣。看到這個答案 - > http:// stackoverflow。com/questions/2578756/how-to-make-authorize-attribute-return-custom-403-error-page-instead-of-redirect –

回答

0

但是,用戶實際上已登錄,並且無法登錄可以糾正用戶身份缺少查看頁面的權限這一事實。

如果他們無法使用允許他們訪問相關資源的帳戶登錄,那麼他們爲什麼要去那裏?

要麼他們故意試圖做一些不應該工作的東西,在這種情況下,我不會對他們的失望抱有那麼多的同情,或者有鏈接或其他導航功能表明他們可以做到這一點,這是一個更大的問題,會導致任何一種方式的挫折。

除此之外,兩種方法都有其支持者。禁止方法的優點是能夠引導用戶做他們能做的事情。登錄提示的優點是可以使用其他帳戶登錄,如果資源是可以以這種方式訪問​​的資源,則可以繼續。

如果您在禁用的錯誤頁面上包含登錄表單,您可以擁有這兩種功能,以涵蓋該情況。

+0

好點。我在考慮兩個主要用途:1)用戶與缺乏權限的人共享鏈接; 2)調試 - 如果我有流氓鏈接或某處有權限,403頁面更有可能使其返回對我來說我可以修復它。 – Matthew

+0

關於第1點,如果我按照某個讓我登錄的人的鏈接登錄(我知道我需要這樣做),或者我意識到我無法登錄。這裏沒有一個很大的勝利,但我會傾向於401。關於第二點,這是你的日誌記錄的問題;如果您可以檢測到有人在登錄時獲得了401,那麼您可以將其記錄爲與僅獲取一個不同的情況,因爲他們尚未登錄。 –

+0

Web服務器應該返回正確的狀態碼。這不是用戶界面問題,這是關於系統的正確配置。當涉及到ADFS時,這變得很重要,並且你陷入重定向循環,因爲它認爲你仍然需要登錄。 – Nacht

相關問題