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);
  }

}