場景: (與ASP.NET web應用程序 - Core或MVC)ViewModel中的ASP.NET模型ID - 安全嗎?
我有Users
和Items
爲每個用戶的數據庫。 這意味着UserId
是Items
表中的foreign key
。
從瀏覽器我登錄爲User
。我得到我的Items
作爲ItemViewModels
的列表,它們通過簡單的api GET請求映射(AutoMapper)到ItemViewModels
。
我想通過一個簡單的API調用更新其中一個項目(應屬於我 - 登錄的用戶)。因此,我通過PUT請求將修改的項目發送回服務器,作爲ItemViewModel
。
第一種方法:
最簡單的方法是將包括在ItemViewModel
項目的數據庫ID,ItemId
, - 所以當我收到被更新爲ItemViewModel
的項目,我可以映射它回到數據庫中的現有項目。
這對我來說聽起來相當不安全,因爲任何人都可以用任何ItemId
修改PUT請求並影響不屬於執行請求的用戶的項目。有什麼我錯過這種方法?
第二種方法:
不通過數據庫PK ItemId
在ItemViewModel
。 請使用其他形式的標識:假設用戶X
有10個項目。它們使用名爲UserItemId
(它也存在於數據庫中)的屬性從1到10進行編號。
然後我就可以通過這個UserItemId
在ItemViewModel
,當我拿回來我可以把它映射到數據庫中的現有項目(如果一切都ok了該請求),或者放棄它,並拒絕如果UserItemId
沒要求不匹配登錄用戶項目中的任何內容。
有人使用這種方法嗎?
優點:
用戶只能訪問它自己的項目,可以在不影響其他人的,因爲它不知道實際的項目ID(主鍵),以及任何修改都僅限於它的項目。
缺點:
額外的管理大量必須在服務器端執行這種方法的工作。
還有其他方法嗎?
請考慮上面提到的情況適用於數據庫中客戶端實現可以CRUD的所有實體,所以它不僅僅是上面描述的簡單情況。
建議的解決方案應該適用於整個應用程序數據。
我知道這個問題已被問到here和here但第一個沒有令人滿意的答案,我不認爲第二個真的適用於我的情況,因爲它只是處理UserId。
謝謝。
EDIT
請考慮上述Item
爲包含各多個複雜subItems
與在db一個表中的聚合根。這個問題同樣適用於主要的Item
。這意味着每個subItem
都作爲ViewModel傳遞給客戶端。
我應該指出,關於進一步將更新請求:
對於第一種方法,如果允許用戶更改的項目,我可以很容易地檢查。但我也應該爲此做所有
subItems
。對於第二種方法,我可以檢查用戶是否可以更新
Item
如下:我獲得進入視圖模型的userItemId
- >我得到的所有記錄在從數據庫用戶的項目,並試圖找到一個匹配同樣userItemId
,如果我得到一個命中,然後我繼續更新。
絕不信任用戶輸入。您必須**總是**在服務器上進行驗證。檢查當前用戶是否有權根據其ID來更新對象,並且只有當它們具有時才執行更新(否則重定向到錯誤頁面) –