EDIT -只是一个快速编辑,以一个明确的问题开始!我本质上问的是,当从视图发回时,保护我的实体标识符的最有效方法是什么?
我一直在考虑在编辑视图模型时保护POST上的ID的方法。让我们以实体
为例public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
及其对应的视图模型:
public class PostViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
现在,当我将这个视图模型传递给一个允许用户编辑它的视图时,我将这样做:
public ActionResult EditPost(PostViewModel viewModel)
{
Post post = database.Posts.Single(p => p.Id.Equals(viewModel.Id));
post.Title = viewModel.Title;
post.Content = viewModel.Content;
database.Entry(post).State = System.Data.EntityState.Modified;
database.SaveChanges();
return View(viewModel);
}
或者像这样通过参数列表传递ID:
public ActionResult EditPost(int postId, PostViewModel viewModel)
{
Post post = database.Posts.Single(p => p.Id.Equals(postId));
// and the rest
}
无论哪种方式,我们都需要返回要更新的实体的标识符以及POST数据。我们如何确保更新的实体是预期的实体?
我想我们可以验证用户是否有足够的访问权限来更新这个实体…但是,如果用户的帐户被泄露,并且一些随机的黑客开始使用他们的帐户注入随机id怎么办?随机更新各种Post
有一个复杂的(如GUID)标识符可能被推荐用于实体,这将使猜测困难得多,但这会使您的漂亮和友好的url看起来有点吓人的普通用户,当查看Post
时不得不传递它。
我们如何做到两全其美呢?保持干净的url,但保护我们的实体免受注入攻击?
这是直接引用攻击,根据swap建议,您可以
- 通过将id交换为guid来混淆id,然后将映射保存在内存/session
- 保存对会话中项目的引用,并确保它与返回的相同
Decorate get action with attribute
on gets, attribute clears item list from session
Pull Item from db
store items id in session for item
decorate post action with attribute
attribute makes sure modelstate is valid first (saves double validating)
attribute looks in session for id
attribute checks the id against the stored value
if id matches, action can continue
if id doesn't match, an entry is made in modelstate
使用这种方法,您可以保护自己免受有人在burpsuite等工具中篡改您的id或使用浏览器的控制台模式来翻转隐藏字段。
同样,作为这个过程的开始,始终确保您的get项目不是盲目地从数据库中获取,而是首先确保该人实际上可以获得该项目,即。属于他们的数据集等等等等
你说的是防止某人在应该编辑记录1的时候篡改他们的表单,说他们正在更新记录2,对吗?而不是阻止人们发现用户ABC发布的帖子的身份是1?
也许用标识列和来创建表和视图模型会简单一点。您所有的url/GET进程都可以使用标识来构建,并且您可以使用向导来完成所有的POST处理。这将使您不必构建一些内存中的映射,使用会话键,创建操作过滤器等。我和你一样——我想减少你对会话的依赖程度,因为它是时间敏感的;一旦你的会话过期,你保存在内存中的映射也会过期,所以它总是返回一个假阴性。这可能会消除数据层的一些可重用性。
编辑:但我认为最好的保护是像你说的那样-验证编辑记录的帐户有权编辑记录。如果您将其与guid(或表单上加密的内容)结合使用,则很难随机猜测记录。
您还可以尝试在POST表单中添加某种散列算法。比如,对身份、创建帖子的用户、帖子创建的时间以及最终用户无法看到的实体上的一些随机不可更新的盐进行散列。您还可以包含一些随机的内容(例如页面呈现时的刻度时间),以确保每次加载页面时哈希值都是唯一的,这将防止某人在帐户受到威胁时生成指南/哈希值(您需要在单独的字段中发布刻度)。您的验证过程将把POST的哈希值与实体上那些相同字段的哈希值进行匹配,只有在哈希值匹配时才执行更新。但这对我来说似乎太过分了。