将ActionResult函数声明为private以防止直接URL访问

时间:2011-09-13 05:51:26

标签: c# .net asp.net-mvc

在我的ASP .NET MVC 3 Web应用程序中,我使用了很多部分视图。我在某些情况下通过正常的渲染调用

使用这些部分视图
<div id="attributes">
   @Html.Partial("_DeviceAttributesPartial", Model.DeviceAttributes)
</div>

在其他情况下使用AJAX:

$.ajax({
   url: '@Url.Action("GetDeviceAttributes")',
   type: 'POST',
   data: { deviceID: device, deviceTypeID: devicetype, deviceModelID: devicemodel },
   success: function (result) {
      // when the AJAX succeeds refresh the device model drop down holder
      $('#attributes').html(result);
   }
});

我试图找到一种方法来阻止用户直接进入我的部分视图ActionResults,例如:

public ActionResult GetDeviceModelList(int deviceTypeID)
{
   var model = new EditDeviceViewModel();

   var deviceType = _db.DeviceTypes.Single(t => t.ID == deviceTypeID);
   model.DeviceModelList = new SelectList(_db.DeviceModels.Where(m => m.DeviceType.ID == deviceType.ID), "ID", "Model");

   return PartialView("_DeviceModelListPartial", model);
}

我偶然发现this answer只是做出了private行动。我试了一下它似乎有效,但我对此感到不安,不知道可能会发生什么其他副作用。

所以我的问题是:

  • 将行动设置为private是否明智?
  • 这样做可能会产生哪些其他副作用?
  • 仅通过POST
  • 提供的操作如何?

NB:大多数部分操作结果函数都是[HttpPost],所以我认为无论如何都不能访问它们。

3 个答案:

答案 0 :(得分:3)

降低操作可见性将阻止该操作在控制器外部可用。由[HttpPost]属性修饰的动作可供所有人使用,但只能通过POST http请求,这比普通用户要做的要多。

考虑使用您不会通过POST访问的[ChildActionOnly]属性来修饰操作,而是使用[HttpPost]修饰这些操作。

答案 1 :(得分:2)

您可以创建一个过滤器,检查请求是否为ajax请求,如果不是则返回404

[AjaxResult]

然后,您可以使用

修饰控制器方法
filterContext.Result = new HttpUnauthorizedResult();

根据您的具体情况,您也可以

.run(function ($http) {
       $http.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
 });

这将返回401而不是404。

您仍然可以使用RenderPartial并阻止对动作结果的任何非ajax请求。

在尝试自己实现之后,请务必注意,必须确保HTTP标头“X-Requested-With”设置为“XMLHttpRequest”。对于Ajax请求,这显然不是问题,但是对于angular,您需要在模块声明的末尾标记这个:

{{1}}

答案 2 :(得分:1)

将操作标记为私有会使此操作无法访问。就像行动不再存在一样。当您使用带有RenderPartial方法的partials时,您没有调用相应的控制器操作。如果使用Html.RenderAction调用控制器操作,则可以使用[ChildActionOnly]属性修饰此操作。您可以查看following blog post以更好地理解两者之间的区别。