2009-11-09 50 views
0

爲了讓用戶和網站管理員對我的申請,我決定這條航線上查看/添加/編輯/刪除數據:減少重複的代碼在控制器動作

routes.MapRoute("ClientRoute", 
     "{account}/{controller}/{action}/{id}", 
     new { controller = "Home", action = "Index", id = "" }); 

導致路線,如:mvcapp.net/ 1234 /接觸/添加。

爲了讓用戶{管理員除外}訪問其他客戶端的數據,我在控制器操作中添加了以下代碼。

... 
    var model = repos.GetSomeData(); 
    if (User.IsInRole("Admin") == false) { 
    if (account == Profile["Client"]) 
     return View(model); 
    else 
     return View("WrongClient"); 
    } 
... 

這樣做的最好方法是什麼?

解我

public class BaseController : Controller { 
    protected override OnActionExecuting(ActionExecutingContect filterContext) { 
     if (filterContext.RouteData.Values["account"] != null) { 
     string client = filterContext.RouteData.Values["account"].ToString(); 
     if (User.IsInRole("admin") == false) { 
      if (Profile.Clients.Contains(account) == false) 
       filterContext.Result = new ViewResult() {ViewName = "WrongClient"}; 
      } 
     } 
    } 
} 

回答

0

我不確定Profile [「AccountNumber」]正在做什麼(或Profile是從哪裏來的),但假設您可以隨時創建該對象(或者它已經創建);

你可以做以下(這發生在你的控制器):

protected override void ExecuteCore() 
{ 
    var model = repos.GetSomeData(int.Parse(base.RouteData.Values["client"]))); 
    if (User.IsInRole("Admin") == false && Profile["AccountNumber"].ToString() != model.AccountNumber) 
    { 
      ViewData["Error"] = "You can't access this page"; 
      View("WrongClient").ExecuteResult(ControllerContext); 
    } 
    else 
      base.ExecuteCore(); 

} 

你可以把這個在你需要的所有控制器,或者控制器繼承實現此功能的控制器基類。如果你是管理員,需要訪問特定用戶的信息(假設我想使用的用戶創建了同樣的觀點)http://forums.asp.net/t/1382514.aspx

+0

HttpContext.Profile – 2009-11-09 19:48:59

+0

在這種情況下,我建議只檢查「客戶端」是否與用戶的id相匹配(假設您使用clientid作爲User.Identity.Name) – Omar 2009-11-09 23:03:08

+0

Paul Balmire的回覆(第5或第6條)讓我知道解決方案我選擇。 – 2009-11-11 19:30:24

1

新界西堆填你可以寫你的資料庫的方法,使他們只返回客戶端的數據爲適當的帳號。只需將帳號傳遞給存儲庫方法即可。

如果您關心將用戶信息傳遞到存儲庫方法(如Jabe在他的評論中討論的那樣),那麼您可以從存儲庫返回一個IQueryable,然後運行一個Linq查詢來進行安全修整。

+0

:取自

主意? – Omar 2009-11-09 18:58:21

+0

您也可以將管理標誌傳遞給存儲庫方法。 – 2009-11-09 19:06:03

+0

可能有爭議,但存儲庫不應該知道用戶。恕我直言,它應該更像「給身份證,獲取數據」。 – Jabe 2009-11-09 19:51:20

0

對於這個特定的例子,A​​zam Sharp在他的blog上有一個可能的解決方案。我在五分鐘之前從字面上理解了這篇文章。希望能幫助到你!

+0

再看一遍 - 這並不直接解決您的需求,但我仍然認爲它可以適應您正在嘗試做的事情。 – 2009-11-09 18:22:47

+0

我對博客海報處理刪除的方式並不狂熱。刪除操作應始終由POST完成,而不是通過GET完成。 – 2009-11-09 18:30:11

+0

@羅伯特 - 我一般同意。我更喜歡這篇文章的總體思路,而不是實施。雖然,BaseController可以做的很好的例子。 – 2009-11-09 18:56:21

0

考慮到您已從配置文件中獲得該信息,實際上是否有必要讓客戶成爲路線的一部分?

就處理它而言它是存儲庫級別(如上所述) - 這可能會有點棘手,因爲可能會阻止訪問某些業務流程內部所需的數據,也不允許用戶訪問它。當然,你可以創建單獨的過濾/未過濾方法來處理這個問題。而且,這可能是不會混淆客戶數據的方式。

大部分時間在我們的應用程序中,它只是被添加/插入/刪除的頂級項目,需要以某種方式限制訪問。它也只是一個有限的數據集,需要以這種方式進行限制,所以我通常會編寫代碼,如果違反了該項的訪問規則,就會在控制器中拋出某種異常。

如果您的應用程序的規則非常相似,您可以通過很多方法避免重複該代碼。一個自定義的ActionFilter或自定義控制器基類都可以想到。如果你的數據庫中的每一行都有一個客戶端ID或一些這樣的方案,另一個選擇是讓你的域對象實現一個暴露這個ID的接口。然後,您可以編寫可重用的代碼(混入式擴展方法等),使用此接口作爲應用各種安全規則的基礎。

+0

路由中不需要客戶端。我認爲用戶{客戶和管理員}會更容易。 – 2009-11-09 19:53:16

+0

難道這不會讓用戶更難嗎?要直接訪問某個url,他們還必須輸入客戶端ID。查看上面的代碼,您還必須根據已知的「已知」配置文件值驗證此值。除非我錯過了一些東西(這是很有可能的),似乎所有這些都是多餘的。只要配置文件中包含的值是安全和正確的,您就不必處理路由值。 – Krazzy 2009-11-09 20:20:42

+0

我的客戶有一個或多個帳號,他們都很熟悉。他們的生命,也就是$$,取決於這些數字。這並不意味着它不是多餘的。它只是一個想法,讓他們不必總是從列表中選擇。 – 2009-11-09 22:46:22