Токен Orchard CMS Ajax для защиты от подделки при входе в систему - PullRequest
10 голосов
/ 27 января 2012

Я создаю модуль Orchard CMS, который я тестирую на сайте 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, ActionDescriptor actionDescriptor) в System.Web.Mvc.ControllerActionInvoker.InvokeAction (ControllerContext controllerContext, String actionName) InnerException:

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

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

Спасибо, Brian

Ответы [ 2 ]

23 голосов
/ 28 января 2012

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

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

Существует еще решение, если у вас есть отдельный файл сценария из вашего представления, который заключается в том, чтобы сохранить токен защиты от подделки внутри переменной javascript, объявленной из представления, а затем использовать его из сценария:

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

Тогда из сценария:

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

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

3 голосов
/ 27 января 2012

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

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

$("#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");
        }
    });
});
...