Поиск…


Вступление

Флаг анти-подделки может использоваться для защиты вашего приложения от подделки подпроса. Чтобы использовать эту функцию, вызовите метод AntiForgeryToken из формы и добавьте атрибут ValidateAntiForgeryTokenAttribute к методу действий, который вы хотите защитить.

Создает скрытое поле формы (токен анти-подделки), который проверяется при отправке формы.

Синтаксис

  • @ Html.AntiForgeryToken ()

замечания

При отправке запроса ajax с помощью токена CSRF ( __RequestVerificationToken ) убедитесь, что тип содержимого не установлен в application/json . Если вы используете jQuery, он автоматически устанавливает тип содержимого в application/x-www-form-urlencoded который затем распознается ASP.NET MVC.

предосторожность

Будьте осторожны при установке этого значения. Использование его ненадлежащим образом может открыть уязвимости безопасности в приложении.

Основное использование

Вспомогательный метод @Html.AntiForgeryToken() защищает от атак с подделкой запросов на межсайтовый запрос (или CSRF).

Его можно использовать, просто используя помощник Html.AntiForgeryToken() в одной из существующих форм и украсив соответствующее ему действие Controller с атрибутом [ValidateAntiForgeryToken] .

Razor (YourView.cshtml)

@using (Html.BeginForm("Manage", "Account")) {
    @Html.AntiForgeryToken()  
    <!-- ... -->
}

ИЛИ ЖЕ

<form>
    @Html.AntiForgeryToken()
    <!-- ... -->
</form>

Контроллер (YourController.cs)

Метод целевого действия:

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult ActionMethod(ModelObject model)
{
    // ...
}

Отключить эвристический чек идентификации

Часто вы увидите исключение

Anti forgery token is meant for user "" but the current user is "username"

Это связано с тем, что токен Anti-Forgery также связан с текущим зарегистрированным пользователем. Эта ошибка появляется, когда пользователь входит в систему, но их токен по-прежнему связан с анонимным пользователем для сайта.

Есть несколько способов исправить это поведение, но если вы предпочитаете не использовать токены CSRF, связанные с входом в систему пользователя, вы можете отключить эту функцию.

Поместите эту строку в свой файл Global.asax или аналогичную процедуру запуска приложения.

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;

Проверка всех сообщений

Из-за уязвимости, вызванной CSRF, обычно считается хорошей практикой проверять AntiForgeryToken на всех HttpPosts, если нет веской причины не делать этого (некоторые технические проблемы с сообщением, есть еще один механизм аутентификации и / или пост не мутирует состояние, как сохранение в db или файл). Чтобы вы не забыли, вы можете добавить специальный файл GlobalActionFilter, который автоматически проверяет все HttpPosts, если действие не украшено специальным атрибутом «игнорировать».

[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            bool skipCheck = filterContext.ActionDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttribute), true)
                || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttribute), true);

            if (skipCheck)
                return;


            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

/// <summary>
/// this should ONLY be used on POSTS that DO NOT MUTATE STATE
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class DontCheckForAntiForgeryTokenAttribute : Attribute { }

Чтобы убедиться, что он проверяется на все запросы, просто добавьте его в свои глобальные фильтры действий

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //...
        filters.Add(new ValidateAntiForgeryTokenOnAllPosts());
        //...
    }
}

Предварительное использование: применять фильтр Antiforgery по умолчанию для каждого POST

Мы можем забыть применить Antiforgery attribute для каждого запроса POST поэтому мы должны сделать это по умолчанию. В этом примере Antiforgery filter всегда будет применяться к каждому запросу POST .

Сначала создайте новый фильтр AntiForgeryTokenFilter :

//This will add ValidateAntiForgeryToken Attribute to all HttpPost action methods
public class AntiForgeryTokenFilter : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        List<Filter> result = new List<Filter>();

        string incomingVerb = controllerContext.HttpContext.Request.HttpMethod;

        if (String.Equals(incomingVerb, "POST", StringComparison.OrdinalIgnoreCase))
        {
            result.Add(new Filter(new ValidateAntiForgeryTokenAttribute(), FilterScope.Global, null));
        }

        return result;
    }
}

Затем зарегистрируйте этот настраиваемый фильтр в MVC, Application_Start:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {    
        //Cactch generic error
        filters.Add(new HandleErrorAttribute());

        //Anti forgery token hack for every post request
        FilterProviders.Providers.Add(new AntiForgeryTokenFilter());            
    }
}  



public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

Итак, теперь все ваши POST запросы защищены по умолчанию с использованием атрибутов Antiforgery, поэтому нам больше не нужно иметь атрибут [ValidateAntiForgeryToken] для каждого метода POST.

Использование AntiForgeryToken с запросом JQuery Ajax

Сначала вы создаете форму

@using (Html.BeginForm())
{
  @Html.AntiForgeryToken()
}

Метод действия

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(FormViewModel formData)
{
    // ...
}

скрипт

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
var formData = new FormData($('form')[0]);
$.ajax({
    method: "POST",
    url: "/demo/test",
    data: formData ,
    success: function (data) {
  console.log(data);
    },
    error: function (jqXHR, textStatus, errorThrown) {
        console.log(errorThrown);
    }
})
</script>

Убедитесь, что contentType не настроен ни на что иное, кроме application/x-www-form-urlencoded и если его не указан Jquery по умолчанию для application/x-www-form-urlencoded



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow