Recherche…


Introduction

Le jeton anti-contrefaçon peut être utilisé pour protéger votre application contre la falsification de requêtes intersites. Pour utiliser cette fonctionnalité, appelez la méthode AntiForgeryToken à partir d'un formulaire et ajoutez l'attribut ValidateAntiForgeryTokenAttribute à la méthode d'action que vous souhaitez protéger.

Génère un champ de formulaire masqué (jeton anti-contrefaçon) validé lors de la soumission du formulaire.

Syntaxe

  • @ Html.AntiForgeryToken ()

Remarques

Lorsque vous soumettez une requête ajax avec un jeton CSRF ( __RequestVerificationToken ), assurez-vous que le type de contenu n'est pas défini sur application/json . Si vous utilisez jQuery, il définit automatiquement le type de contenu sur application/x-www-form-urlencoded qui est alors reconnu par ASP.NET MVC.

Mise en garde

Soyez prudent lorsque vous définissez cette valeur. Son utilisation incorrecte peut ouvrir des vulnérabilités de sécurité dans l'application.

Utilisation de base

La méthode d'assistance @Html.AntiForgeryToken() protège contre les attaques par falsification de requête intersite (ou CSRF).

Vous pouvez l'utiliser simplement en utilisant l' Html.AntiForgeryToken() dans l'un de vos formulaires existants et en décorant son action de contrôleur correspondante avec l'attribut [ValidateAntiForgeryToken] .

Razor (YourView.cshtml)

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

OU

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

Contrôleur (YourController.cs)

La méthode d'action cible:

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

Désactiver le contrôle heuristique d'identité

Souvent, vous verrez une exception

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

Cela est dû au fait que le jeton Anti-Forgery est également lié à l'utilisateur actuellement connecté. Cette erreur apparaît lorsqu'un utilisateur se connecte mais que son jeton est toujours lié à un utilisateur anonyme du site.

Il existe plusieurs manières de résoudre ce problème, mais si vous préférez ne pas avoir de jetons CSRF liés à l'état de connexion d'un utilisateur, vous pouvez désactiver cette fonctionnalité.

Placez cette ligne dans votre Global.asax ou dans la logique de démarrage d'une application similaire.

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;

Valider tous les messages

En raison de la vulnérabilité causée par CSRF, il est généralement considéré comme une bonne pratique de rechercher un AntiForgeryToken sur tous les HttpPosts à moins qu’il n’y ait une bonne raison de le faire (problème technique avec la publication, autre mécanisme d’authentification et / ou post ne modifie pas l'état comme l'enregistrement dans une base de données ou un fichier). Pour vous assurer de ne pas oublier, vous pouvez ajouter un GlobalActionFilter spécial qui vérifie automatiquement tous les HttpPosts à moins que l'action ne soit décorée avec un attribut spécial "ignore".

[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 { }

Pour vous assurer qu'il est vérifié sur toutes les demandes, ajoutez-le simplement à vos filtres d'action globale.

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

Utilisation avancée: appliquez le filtre Antiforgery par défaut pour chaque POST

Nous pourrions oublier d'appliquer l' Antiforgery attribute pour chaque requête POST afin que nous puissions le faire par défaut. Cet exemple s'assurera que le Antiforgery filter sera toujours appliqué à chaque requête POST .

AntiForgeryTokenFilter créer un nouveau filtre 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;
    }
}

Enregistrez ensuite ce filtre personnalisé dans 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);
    }
}

Ainsi, toutes vos requêtes POST sont désormais protégées par défaut à l'aide d'attributs Antiforgery. Il n'est donc plus nécessaire d'avoir l'attribut [ValidateAntiForgeryToken] sur chaque méthode POST.

Utiliser AntiForgeryToken avec Jquery Ajax Request

Tout d'abord, vous créez le formulaire

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

Méthode d'action

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

Scénario

<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>

Assurez-vous que contentType n'est pas défini sur autre chose que application/x-www-form-urlencoded et si son Jquery non spécifié est défini par défaut sur application/x-www-form-urlencoded



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow