Asp.net-Mvc

模型所有權檢查

  • January 2, 2016

在修改(更新或刪除)模型之前的控制器中,我試圖驗證執行操作的使用者是否真正擁有他們試圖修改的對象。

我目前正在方法級別執行此操作,這似乎有點多餘。

[HttpPost]
public ActionResult Edit(Notebook notebook)
{
   if (notebook.UserProfileId != WebSecurity.CurrentUserId) { return HttpNotFound(); }

   if (ModelState.IsValid)
   {
       db.Entry(notebook).State = EntityState.Modified;
       db.SaveChanges();
       return RedirectToAction("Index");
   }
   return View(notebook);
}

是否有一種通用的方法可以在各種模型中重複使用?

是否有可能用一個來做到這一點ActionFilter

我可以看到您所擁有的一個問題 - 您依賴使用者輸入來執行安全檢查。

考慮你的程式碼

if (notebook.UserProfileId != WebSecurity.CurrentUserId)

Notebook 來自模型綁定。所以 UserProfileId 來自模型綁定。你可以很高興地偽造它——例如,我使用 Firefox 的 TamperData 來更改隱藏的 UserProfileId 的值以匹配我的登錄名,然後我就走了。

我最終要做的事情(在服務中,而不是在控制器中)是在一個文章上根據傳遞的唯一 id 從數據庫中拉回記錄(例如,Edit/2 將使用 2),然後檢查 User.Identity。我在返回的數據庫記錄中擁有的目前所有者欄位的名稱(嗯,傳遞的身份參數)。

因為我從數據庫(儲存庫,無論如何)中撤回,所以屬性不會為此工作,而且我不確定您是否可以在屬性的方法中足夠通用。

過濾器方法可能如下所示:

public class VerifyOwnership : IActionFilter
{
   public void OnActionExecuting(ActionExecutingContext filterContext)
   {
       foreach(var parameter in filterContext.ActionParameters)
       {
           var owned  = paramter.Value as IHaveAnOwner;
           if(owned != null)
           {                    
               if(owned.OwnerId != WebSecurity.CurrentUserId)
               {
                   // ... not found or access denied
               }
           }
       }
   }

   public void OnActionExecuted(ActionExecutedContext filterContext)
   {

   }
}

假設像 Notebook 這樣的模型實現了特定的介面。

public interface IHaveAnOwner
{
   int OwnerId { get; set; }
}

Blowdart 有一個很好的觀點,即使用者可以在文章中篡改 OwnerId。我相信他們也可以篡改他們的身份驗證票,但我相信他們必須知道另一個使用者的票並篡改兩者才能讓 ID 與另一個使用者匹配。

引用自:https://stackoverflow.com/questions/12500085