Asp.net-Mvc
模型所有權檢查
在修改(更新或刪除)模型之前的控制器中,我試圖驗證執行操作的使用者是否真正擁有他們試圖修改的對象。
我目前正在方法級別執行此操作,這似乎有點多餘。
[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 與另一個使用者匹配。