2014-02-06 35 views
1

限制訪問控制器的正確方法是什麼?根據某些條件限制對控制器的訪問權限,而不是用戶身份驗證

例如,我可能有「ProductReviewController」,我希望能夠檢查該控制器是否可在當前存儲中訪問並啓用。我不是在代碼之後做這件事,而是對如果不符合這個標準而停止用戶進入控制器的方法感興趣。我希望這個請求能夠繼續進行,就好像控制器從不在那裏一樣(所以也許扔404)。

我的想法至今:

  1. 數據註解即[IsValidController]。哪個Attribute類會從我派生 - 授權似乎並不適合,我會將此與用戶身份驗證相關聯。另外,如果不符合標準,我不確定正確的答案是什麼(但我想這取決於它來自於Attribute)。我可以把這個數據註釋對我的基礎控制器。

  2. 找到頁面生命週期中較低的位置,並且如果控制器不符合我的標準,則停止用戶點擊控制器。即創建我自己的控制器廠在7點這裏描述:http://blogs.msdn.com/b/varunm/archive/2013/10/03/understanding-of-mvc-page-life-cycle.aspx

,這是什麼最好的方法?

注意:目前,我傾向於選項1,並使用AuthorizeAttribute,其代碼如下所示。雖然我覺得我濫用AuthorizeAttribute

public class IsControllerAccessible : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (!CriteriaMet()) 
      return false; 

     return true; 
    } 

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     filterContext.Result = new RedirectToRouteResult(
     new RouteValueDictionary(
      new 
      { 
       controller = "Generic", 
       action = "404" 
      }) 
     ); 
    } 
} 

回答

3

我覺得你對AuthorizeAttribute感到困惑。它是一個動作過濾器,而不是數據註釋。 Data Annotations爲validatioj裝飾模型屬性,Action Filter的裝飾控制器動作檢查控制器的上下文並在動作執行之前執行某些操作。

因此,限制對控制器動作的訪問權限是AuthorizeAttribute的存在條件,所以讓我們使用它!

隨着SO的好鄉親的幫助下,我創建了限制訪問基於訪問Directory組被部分行動(甚至控制器)用戶行爲過濾器:

public class AuthorizeADAttribute : AuthorizeAttribute 
{ 
    public string Groups { get; set; } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (base.AuthorizeCore(httpContext)) 
     { 
      /* Return true immediately if the authorization is not 
      locked down to any particular AD group */ 
      if (String.IsNullOrEmpty(Groups)) 
       return true; 

      // Get the AD groups 
      var groups = Groups.Split(',').ToList<string>(); 

      // Verify that the user is in the given AD group (if any) 
      var context = new PrincipalContext(ContextType.Domain, "YOURADCONTROLLER"); 
      var userPrincipal = UserPrincipal.FindByIdentity(context, 
               IdentityType.SamAccountName, 
               httpContext.User.Identity.Name); 

      foreach (var group in groups) 
      { 
       try 
       { 
        if (userPrincipal.IsMemberOf(context, IdentityType.Name, group)) 
         return true; 
       } 
       catch (NoMatchingPrincipalException exc) 
       { 
        var msg = String.Format("While authenticating a user, the operation failed due to the group {0} could not be found in Active Directory.", group); 
        System.ApplicationException e = new System.ApplicationException(msg, exc); 
        ErrorSignal.FromCurrentContext().Raise(e); 
        return false; 
       } 
       catch (Exception exc) 
       { 
        var msg = "While authenticating a user, the operation failed."; 
        System.ApplicationException e = new System.ApplicationException(msg, exc); 
        ErrorSignal.FromCurrentContext().Raise(e); 
        return false; 
       } 
      } 
     } 
     return false; 
    } 
} 

注意這將返回一個401 Unauthorized,這是有道理的,而不是你上面指出的404 Not Found。現在

,在這個神奇的是,你可以通過在操作層面將它限制訪問:

[AuthorizeAD(Groups = "Editor,Contributer")] 
public ActionResult Create() 

或者在控制器級別:

[AuthorizeAD(Groups = "Admin")] 
public class AdminController : Controller 

甚至在編輯FilterConfig.cs全球`/ App_Start':

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new Code.Filters.MVC.AuthorizeADAttribute() { Groups = "User, Editor, Contributor, Admin" }); 
    } 

完全真棒醬!

P.S.你在第二點提到頁面生命週期。在MVC中沒有這樣的事情,至少在Web Forms的意義上你不會想到。這對我來說是件好事,因爲事情大大簡化了,我不必記住十幾種不同的生命週期事件以及他們每一個人都被提出來的東西!

+0

好的,謝謝你對數據註釋的澄清 - 我的術語錯了。我剛剛使用'AuthorizeAttribute'編寫了自己的版本,並且運行良好。我只是想確保這是正確的方式。當我提到生命週期時,我指的是這種事情:http://blogs.msdn.com/b/varunm/archive/2013/10/03/understanding-of-mvc-page-life-cycle。 ASPX。我特別想到重申第7點並創建一個定製控制器工廠。 – webnoob

+0

p.s'404 not found'在我的情況下是正確的答案。不是未經授權的用戶,而是不應該顯示內容的站點(這意味着用戶需要跟蹤緩存的鏈接或其他內容)。 – webnoob

+0

然後代碼應該可能駐留在您的控制器本身,因爲它負責根據用戶交互提供正確的視圖。如果用戶提供產品ID,請讓控制器檢查存儲中是否存在該產品,如果不存在,則重定向到指示這樣的特定視圖。 –

相關問題