Asp.net mvc Как запретить браузеру вызывать метод действия?
У меня есть два действия внутри моего контроллера (shoppingCartController)
public ActionResult Index()
{
//some stuff here
return View(viewModel);
}
public ActionResult AddToCart(int id)
{
return RedirectToAction("Index");
}
В любом случае, чтобы пользователи не могли напрямую вызвать действие индекса, набрав URL-адрес в браузере?
Например: Если пользователь просматривает shoppingCart/index
, перенаправляется в Home/Index.
Ответы
Ответ 1
Вы можете использовать атрибут [ChildActionOnly]
вашего метода действий, чтобы убедиться, что он не вызван напрямую, или используйте ControllerContext.IsChildAction
свойство внутри вашего действия, чтобы определить, хотите ли вы перенаправить.
Например:
public ActionResult Index()
{
if(!ControllerContext.IsChildAction)
{
//perform redirect here
}
//some stuff here
return View(viewModel);
}
Если вы не можете сделать действие "Индекс" дочерним действием, вы всегда можете проверить реферер, понимая, что он не является надежным и может быть подделан. См:
Как получить URL-адрес реферера в действии ASP.NET MVC?
Ответ 2
Попробуйте сделать это действие контроллера индекса как private
. Метод с private
модификатором доступа не должен быть доступен из внешнего класса.
И затем, вместо того, чтобы вызывать RedirectToAction
из AddToCart, вызывать его как простой метод, как показано ниже:
private ActionResult Index()
{
//some stuff here
return View(viewModel);
}
public ActionResult AddToCart(int id)
{
return Index();
}
Ответ 3
Если вы беспокоитесь о том, что пользователь вводит URL-адрес, то использование атрибута HttpPost должно препятствовать тому, чтобы ваше действие вызывалось таким образом: -
[HttpPost]
public ActionResult AddToCart(int id)
{
Это предотвращает вызовы GET от этого действия. Однако это не мешает кому-то писать фиктивную форму и POSTing к вашему действию.
Если вы беспокоитесь о чем-то более злонамеренном, вы можете реализовать какую-то форму токена анти-подделки, там есть хорошая информация о том, что здесь.
ИЗМЕНИТЬ
ОК, поэтому повторное чтение вопроса, приведенное выше, не совсем решает вашу проблему.
Как насчет маршрута? если у вас есть что-то вроде ниже, это предотвратит вызов ShoppingCart/Index и перенаправление пользователя на индекс вашего сайта.
routes.MapRoute(
"ShoppingCartIndex",
"ShoppingCart/Index",
new { controller = "Home", action = "Index" }
);
Ответ 4
Если SessionState включен, вы можете использовать контроллер TempData для достижения своей цели. Установите TempData в действие AddToCart и покажите только представление индекса, если действие индекса может получить ключ TempData, установленный в действии AddToCart.
Если вам нужно это для нескольких действий/проектов, используйте комбинацию пользовательского Action Filter и ActionResult. Вот так:
// Controller
[PreventDirectAccess]
public ActionResult Index()
{
//some stuff here
return View(viewModel);
}
public ActionResult AddToCart(int id)
{
return new PreventDirectAccessRedirectToRouteResult(new RouteValueDictionary
{
{"action", "Index"}
});
}
// Filter
public class PreventDirectAccessAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext == null)
throw new ArgumentNullException("filterContext");
if (filterContext.Controller.TempData[PreventDirectAccessRedirectToRouteResult.Executed] == null)
filterContext.Result = new HttpNotFoundResult();
base.OnActionExecuting(filterContext);
}
}
// ActionResult
public class PreventDirectAccessRedirectToRouteResult : RedirectToRouteResult
{
public const string Executed = "PreventDirectAccessRedirectExecuted";
public override void ExecuteResult(ControllerContext context)
{
context.Controller.TempData[Executed] = true;
base.ExecuteResult(context);
}
}
Ответ 5
Здесь написано, как предотвратить прямой доступ браузера к методу действия:
Напишите ниже код в FilterConfig.cs
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class NoDirectAccessAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.UrlReferrer == null ||
filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }));
}
}
}
Теперь примените этот код к вашему методу действий
[NoDirectAccess]
public ActionResult MyActionMethod()
Это ограничит прямой вызов любого класса или действия.
Ответ 6
NonAction - это атрибут, который следует использовать. Это часть библиотеки MVC, поэтому вам не нужно создавать свой собственный атрибут.
Ответ 7
Это не проверено, но я считаю, что вы можете использовать токен проверки подлинности антивируса
В вашем коде на странице вам нужно будет поместить токен проверки в форму, которая должна быть опубликована:
@Html.AntiForgeryToken()
Что производит:
<input name="__RequestVerificationToken" type="hidden" value="s9+jDREFMlNPkAT2zOlmhJZQbbDOzMhuarSTG1BVAC4GeHiNL5VtuQo7CQTF8obw8hEYIQac9YaQh+qVcF0xj0eNO7lVdezz+JxuSKGQo2d2gEdtkEdR+XTTFas4Gh6fjSYc7A1rWF8AAhxjZ9j6GlbRhECZOPAlPAItnjz49QQ=" />
Этот токен автоматически подбирается любым действием, имеющим этот атрибут:
[ValidateAuthenticationToken]
public ActionResult AddToCart(int id)
{
return Index();
}
Если запрос прямой, произойдет ошибка.
Ответ 8
Вы также можете использовать только дочерний атрибут action. Просто делюсь :)
public class MyController {
[ChildActionOnly]
public ActionResult Menu() {
var menu = GetMenuFromDB();
return PartialView(menu);
}
}