2016-10-13 134 views
0

我有以下數據庫結構 DB structure, authentication/authorization part 我必須爲ASP.NET MVC 5站點構建身份驗證/授權。ASP.NET MVC5中的自定義身份驗證和授權?

數據庫模式的工作原理如下:每user屬於group,並且每個group可以被授予/拒絕permission。每個權限相匹配的控制器上的操作(比方說,一個Petitions控制器將有下列行爲:ListViewAddEditDeleteVoteForVoteAgainstRejectApprove,並且每個動作都在Permissions表中的條目) 。

所有這一切的目的是,每當用戶調用一個動作時,該站點就會驗證該用戶是否屬於已被授予該動作許可的組,並作出相應的反應。

舉個例子:假設管理員授予PetitionsListPetitionsViewPetitionsApprovePetitionsReject權限Managers組,PetitionsListPetitionsViewPetitionsAddPetitionsVoteForPetitionsVoteAgainstUsers組。

在這種情況下,這兩個羣體可以

  • 列表請願
  • 查看了一份請願書

經理可以

  • 批准了一份請願書
  • 拒絕了一份請願書

但他們不能

  • 投票請願
  • 投反對票的請願書。

以同樣的方式,用戶可以

  • 添加了一份請願書
  • 投票請願
  • 票反對呈請

但他們不能:

  • 批准請願
  • 拒絕了一份請願書

既不可以編輯或刪除的請願書。

我真的想利用MVC 5中的屬性功能。我的想法是建立自定義屬性,在場景後面執行所有認證/授權。例如:

public class PetitionsController : Controller 
{ 
    [MyCustomAuth(Permission="PetitionsList",Groups="Users,Managers")] 
    public ActionResult List() 
    { 
     //show the list of petitions 
    } 

    [MyCustomAuth(Permission="PetitionsView",Groups="Users,Managers")] 
    public ActionResult View() 
    { 
     //show a specific petition 
    } 

    [MyCustomAuth(Permission="PetitionsAdd",Groups="Users")] 
    public ActionResult Add() 
    { 
     //show add petition form 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsAdd",Groups="Users")] 
    public ActionResult Add(object[] params) 
    { 
     //save new petition 
    } 

    [MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")] 
    public ActionResult Edit(int id) 
    { 
     //show edit petition form 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")] 
    public ActionResult Edit(object[] params) 
    { 
     //save changes to petition 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsDelete",Groups="Admins")] 
    public ActionResult Delete(int_id) 
    { 
     //delete petition 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsVoteFor",Groups="Users")] 
    public ActionResult VoteFor(int id) 
    { 
     //add vote supporting petition 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsVoteAgainst",Groups="Users")] 
    public ActionResult VoteAgainst(int id) 
    { 
     //add vote against petition 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsApprove",Groups="Managers")] 
    public ActionResult Approve(int id) 
    { 
     //approve petition 
    } 

    [HttpPost] 
    [MyCustomAuth(Permission="PetitionsReject",Groups="Managers")] 
    public ActionResult Reject(int id) 
    { 
     //reject petition 
    } 
} 

請注意每個動作的MyCustomAuth屬性。我希望這個屬性能夠說出用戶是否被授權在後臺執行該操作。當然,如果沒有進行身份驗證/授權,該屬性應該重定向到登錄頁面/ 401 /別的地方。

我的問題是,我從哪裏開始?我是否期望在MVC 5中實現一些特殊的接口/繼承?或者我必須從頭開始寫這個?

另外,在此先感謝您閱讀這篇文章牆,並向我提供正確方向的任何提示/指示。

+0

一般來說,數據庫訪問代碼不應該在屬性(不能單元測試的代碼),所以一個更好的解決辦法是有返回一個值的服務,該值指示用戶是否具有正確的權限。每個控制器方法中的代碼可能類似於'if(!_permissionService.HasPermission(DocumentType.Petitions,ActionType.Edit,user.ID){// denied}' –

+0

如何創建驗證用戶訪問指定的操作並從屬性類中調用服務?使測試更容易進行測試,並且我仍然只能在動作上寫出屬性(兩全其美)? –

+0

只需確保您可以使用DI,以便控制器可以建議你看看2個最佳答案[這裏](http://stackoverflow.com/questions/7192543/injecting-dependencies-into-asp-net-mvc-3-action-filters-whats-wrong-有了這個) –

回答

1

我認爲你可以從下面的自定義授權過濾器開始。它還處理兩種情況 - ajax請求和整頁請求。

public class MyCustomAuthAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     public string Permission { get; set; } 
     public string Groups { get; set; } 

     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      bool isauthorized = CheckIfUserIsAuthorized(); 
      if (!isauthorized) 
       context.Result = new HttpUnauthorizedResult(); // mark unauthorized 

      // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
      if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) 
      { 
       filterContext.Result = new JsonResult 
       { 
        Data = new { Success = false, Message = "Unauthorized Access" }, 
        JsonRequestBehavior = JsonRequestBehavior.AllowGet 
       }; 
      } 
      else 
      { 
       base.OnAuthorization(filterContext); 
       if (filterContext.Result is HttpUnauthorizedResult) 
       { 
        HttpContext.Current.Session.Abandon(); 
        System.Web.Security.FormsAuthentication.SignOut(); 
        filterContext.Result = new RedirectResult("Your Login Page."); 
       } 
      } 
     } 

     private bool IsAuthorizedUser() 
     { 
      // use Permission, Groups and your logic 
     } 
    } 

,並使用它,你提到的一樣:

[MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")]