2014-11-20 172 views
7

我是.NET新手,MVC &身份框架。我注意到身份框架允許通過註釋確保單獨的控制器操作。基於權限的授權.net身份

[Authorize] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

我想根據用戶權限確保某些操作。

示例:博客應用程序,其中只有創建博客帖子的用戶可以編輯。

記住這一點,是否有可能執行下面的任一選項?如果是這樣,是否有資源和例子如何最好地實現?

[Authorize(Entity = "Entry", Permission = "Edit", Id = Id)] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

[BlogEntryPermission(Permission = "Edit", Id = Id)] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

凡博客Id從請求抓獲。

任何有關基於權限的身份驗證的信息或方向都將非常感謝。在此先感謝您的幫助。

回答

6

您可以實現您的自定義AuthorizationAttribute在那裏你會指定參數,可以要求

public class AuthorizeEntryPermission : AuthorizeAttribute 
{ 
     public string Permission { get; set; } 

     public AuthorizeEntryPermission(){ 
     } 

     public AuthorizeEntryPermission(string Permission) 
     { 
      this.Permission = Permission; 
     } 

     protected override bool AuthorizeCore(HttpContextBase httpContext) 
     { 
      var id = context.Request.RequestContext.RouteData.Values["Id"]; 
      //check your permissions 
     } 

     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (AuthorizeCore(filterContext.HttpContext)) 
      { 
       // ** IMPORTANT ** 
       // Since we're performing authorization at the action level, the authorization code runs 
       // after the output caching module. In the worst case this could allow an authorized user 
       // to cause the page to be cached, then an unauthorized user would later be served the 
       // cached page. We work around this by telling proxies not to cache the sensitive page, 
       // then we hook our custom authorization code into the caching mechanism so that we have 
       // the final say on whether a page should be served from the cache. 

       HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; 
       cachePolicy.SetProxyMaxAge(new TimeSpan(0)); 
       cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */); 
      } 
      else 
      { 
       //handle no permission 
      } 
     } 

     private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
     { 
      validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
     } 
    } 

得到blogId然後使用它是這樣的:

[AuthorizeEntryPermission(Permission = "Edit")] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 
+0

感謝方向。嘗試訪問路徑變量時遇到問題。 var id = httpContext.Request.Form [「BlogId」];對於像這樣定義的路徑參數不起作用:/ BlogPost/Edit/1。有沒有一種乾淨的方式來訪問這個變量? context.Request.RequestContext.RouteData.Values.ElementAt(2).Value有效但不確定是我想要依賴的東西。 – mcroteau 2014-11-21 00:21:42

+1

@croteau你可以使用'context.Request.RequestContext.RouteData.Values [「Id」]' – 2014-11-21 08:14:57

1

MVC有作用內置。您可以根據需要使角色儘可能細化 - 從本質上使他們成爲權限。例如,你可以把喜歡的角色名:

  • EditBlogPost
  • AddBlogPost
  • ViewBlogPost

然後你可以使用內置的AuthorizeAttribute設定的角色你的控制器上。

[Authorize(Roles = "AddBlogPost")] 
public ActionResult Add(){ 
    //add action 
} 

[Authorize(Roles = "AddBlogPost")] 
[HttpPost] 
public ActionResult Add(BlogModel model){ 
    //add action 
} 

[Authorize(Roles = "EditBlogPost")] 
public ActionResult Edit(int? Id){ 
    //edit action 
} 

[Authorize(Roles = "EditBlogPost")] 
[HttpPost] 
public ActionResult Edit(BlogModel model){ 
    //edit action 
} 

[Authorize(Roles = "ViewBlogPost")] 
public ActionResult View(){ 
    //view action 
} 

然後,它只是一個問題,爲您的數據庫中的每個用戶分配不同的角色。

+2

不過你必須小心這種方法。 cookie限制的最大大小。在大型應用程序中,您可能擁有數千個細化角色 – Shoe 2014-11-20 20:20:38

+0

好點。然而,OP表示他想要一個博客的權限 - 這意味着沒有那麼多控制器可以管理。但是,如果有大量的權限,我同意定製AuthorizeAttribute是更好的方法。 – NightOwl888 2014-11-20 20:40:05

+0

@Shoe - 實際上,您不一定必須將角色存儲在cookie中。您可以將其設置爲每個請求加載它們或將它們緩存給每個用戶。或者,您可以使用按位ID設置角色,因此您需要在Cookie中存儲的唯一東西就是一個長整數。 – NightOwl888 2014-11-21 01:42:52

1

我希望你的問題解決到現在。但值得添加一個新的解決方案。我爲Microsoft Identity 2成員系統實施了基於權限的擴展。這是一個開源項目,您可以訪問到存儲庫中的位置:

https://github.com/Arminkhodaei/Identity-Permission-Extension

用法:

第一種方法:

// GET: /Manage/Index 
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")] 
public async Task<ActionResult> Index(ManageMessageId? message) 
{ 
    //... 
} 

第二種方法:

// GET: /Manage/Users 
public async Task<ActionResult> Users() 
{ 
    if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information.")) 
    { 
     return View(db.GetAllUsers()); 
    } 
    else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information.")) 
    { 
     return View(db.GetUnConfirmedUsers()); 
    } 
    else 
    { 
     return View(new List<User>()); 
    } 
} 
+0

Hi Armin,我可以在控制器級別使用這個AuthorizePermission屬性嗎? – Alienalone 2017-09-25 14:18:52

+0

嗨,@Alienalone,當然可以。要獲得更多說明和澄清,可以查看文檔的**用法**部分。 – 2017-09-25 18:12:37

+0

謝謝。我試過了,它對我來說非常完美。再次感謝你 – Alienalone 2017-09-26 21:21:05