MVC C#:验证当前用户是否有权查看/更新数据

时间:2015-11-17 20:35:57

标签: c# asp.net-mvc security

我们公司目前正在将我们的软件从网络表格改造为MVC,在我们向客户发布之前,它目前处于alpha阶段。简而言之,该应用程序有多个酒店订阅和使用我们的服务。我现在需要确保的核心安全性是没有用户能够访问/修改属于另一家酒店的数据。

我们的模型大多遵循以下两个示例之一:

RoomCategory   (structure: model.HotelID)
--------------
ID
HotelID

Room    (structure: model.Parent.HotelID)
--------------
ID
RoomCategoryID
HotelID

问题在于,当我在〜/ rooms / edit / 1时,我可以将表单操作URL和隐藏字段值从“1”更改为“50”,而房间ID 50属于另一家酒店。这是一个大问题,因为一个用户实际上可以从另一家酒店“窃取”一个房间并将其自己制作!我们的客户不会很开心。

我正在接近问题的方式......

根据当前登录的用户数据(从会话访问),我们知道用户有权管理的酒店(或酒店)。一种方法是验证每个动作调用并执行以下操作:

app.AuthenticateAccess(room.RoomCategory.HotelID);

这样,AuthenticateAccess功能将阻止进一步操作并“重定向”到Unauthorized / NotFound页面,因为它知道Room ID 50属于HotelID 2,而当前用户无法访问它。当然我认为这是一种安全的方法,但这涉及到每个控制器中所有操作的大量重复函数调用。

我一直在寻找在全球范围内克服这一安全挑战的不同可能性:

  1. 最容易的。尽管我个人加密所有ID和隐藏字段值 认为即使没有加密,系统也应该能够 验证每个用户的访问权限。
  2. 在一个单独的抽象类中设置HotelID并让每个模型(哪个 存储关于一个特定酒店的数据)继承自这个摘要 类。也许某种泛型可以在这里完成?
  3. 我们使用存储库/工作单元模式。有一些吗? 限制我们可以检索/更新的数据的方法 目前仅选择酒店ID?
  4. [你真棒的解决方案就在这里。]
  5. 我还有其他一些解决方案,比如使用System.Reflection来搜索所有的HotelID属性,并确保当前用户允许保存/创建的所有数据。但无论如何,让我听听你解决这个问题的方法,因为我还不相信任何我能想到的解决方案。

2 个答案:

答案 0 :(得分:1)

永远不要相信来自客户端的数据。始终在对数据库进行任何更新/事务之前验证发布的数据。

因此,在您的HttpPost操作方法中,您在继续

之前运行清理检查
[HttpPost]
public ActionResult Book(BookingViewModel model)
{
  var isGood = hotelService.DoesCurrentUserHasAccessToRoom(model.RoomId);
  if(isGood)
  {
     //Continue with Saving
     hotelService.BookRoom(model);
     return RedirectToAction("BookingCompleted");
  }
  return View("NotAuthorized");
}

只要您根据需要将它们放入服务中的小型可重用方法中,就不会有重复的代码。

答案 1 :(得分:1)

其他选项是添加HMAC字段以检查敏感数据(隐藏的id字段)是否未被更改,我使用它一次并且再也不使用它,过度杀伤解决方案。

有人说......

我多次遇到同样的问题,我认为几乎相同的选项,从长远来看,我坚持使用最简单的解决方案GetById存储库方法传递CurrentUserId,如:

Entity GetById(int id, int? userId);

为什么?

您正在询问细粒度的授权,只有当您知道操作中涉及的确切记录时才能获得授权,那么为什么不在首先负责获取记录的方法中检查该授权呢?

如果记录存在且用户创建该记录然后返回记录,否则返回null,因为该用户不存在该对象,甚至不打扰返回“您不拥有该对象”类型的消息只是一个简单而简单的404“记录不存在”。

如果您愿意,可以使用ActionFilters尝试相同的方法,类似于this。但是你必须弄清楚如何在filtercontext中检索记录。

对于具有完全访问权限的管理员,如果将null传递给该方法,则可以绕过该检查。