Orchard CMS Ajax Anti-Forgery Token при входе в систему

Я создаю модуль CMS Orchard, который я тестирую на сайте Orchard 1.3.10. Модуль отображает представление деталей для одного из моих сущностей, и у меня есть кнопка "Избранное", которую я бы хотел щелкнуть и сделать сообщение ajax для действия контроллера, чтобы сохранить объект в качестве избранного в базе данных.

В представлении у меня есть следующий код:

<div style="padding: 10px;">
    <span data-id="@Model.Id" id="addFavorite" style="cursor: pointer;">
    [Add Favorite]
    </span>
</div>

<script type="text/javascript">
    $("#addFavorite").click(function () {
        alert("here we go...");
        $.ajax({
            type: "post",
            dataType: "",
            url: "/orchardlocal/mymodule/stuff/AddFavorite",
            data: { id: $(this).data("id") },
            success: function (response) {
                alert("it worked");
            }
        });
    });
</script>

Мое действие контроллера...

[HttpPost]
public ActionResult AddFavorite(int id)
{
    return View();
}

Когда я запустил сайт, не войдя в Orchard, этот код вернётся только в порядке. Если я вхожу в систему и нажимаю "Добавить избранное", я получаю это исключение...

Необходимый токен анти-подделки не был указан или был недействителен.

System.Web.Mvc.HttpAntiForgeryException не был обработан кодом пользователя   Сообщение = Требуемый токен анти-подделки не был указан или был недействителен.   Источник = System.Web.WebPages   ErrorCode = -2147467259   WebEventCode = 0   Трассировки стека:        в System.Web.Helpers.AntiForgeryWorker.Validate(контекст HttpContextBase, соль строки)        в System.Web.Helpers.AntiForgery.Validate(HttpContextBase httpContext, String salt)        в System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext > filterContext)        в Orchard.Mvc.AntiForgery.AntiForgeryAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext) в C:\Code\OrchardDev2\src\Orchard\Mvc\AntiForgery\AntiForgeryAuthorizationFilter.cs: строка 37        в System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)        в System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)   InnerException:

Почему он обрабатывает сообщение по-разному при входе в систему, а не?

Как я могу поставить токен анти-фальсификатора, чтобы избежать этого?

Спасибо, Brian

Ответ 1

ASP.NET MVC по умолчанию не поддерживает генерацию токенов анти-подделки. К счастью, Orchard предоставляет для этого метод расширения.

Вы можете просто изменить свой вызов ajax как есть:

$.ajax({
    type: "post",
    dataType: "",
    url: "/orchardlocal/mymodule/stuff/AddFavorite",
    data: { 
        id: $(this).data("id") },
        __RequestVerificationToken: '@Html.AntiForgeryTokenValueOrchard()'
    },
    success: function (response) {
        alert("it worked");
    }
});

Этот метод полезен, так как вам не нужен существующий FORM на вашей странице. Хотя это решение допустимо только в том случае, если javascript отображается из вида Razor.

По-прежнему существует решение, если у вас есть отдельный файл script из вашего представления, который должен сохранить токен анти-подделки внутри переменной javascript, объявленной из представления, а затем использовать его из script:

@using(Script.Head()) {
<script type="text/javascript">
//<![CDATA[
    var antiForgeryToken = '@Html.AntiForgeryTokenValueOrchard()';
//]]>
</script>
}

Затем из script:

data: { 
    id: $(this).data("id") },
    __RequestVerificationToken: antiForgeryToken 
}

Если нет, то решение, предложенное Дарином, будет правильным путем.

Ответ 2

Как я могу поставить токен анти-фальсификатора, чтобы избежать этого?

Это будет зависеть от того, где скрытое поле, содержащее токен анти-подделки, находится на странице. Например:

$("#addFavorite").click(function () {
    var token = $(':input[name="__RequestVerificationToken"]').val();
    $.ajax({
        type: "post",
        dataType: "",
        url: "/orchardlocal/mymodule/stuff/AddFavorite",
        data: { 
            __RequestVerificationToken: token,
            id: $(this).data("id") 
        },
        success: function (response) {
            alert("it worked");
        }
    });
});