Buscar..


Introducción

El token anti-falsificación se puede usar para ayudar a proteger su aplicación contra la falsificación de solicitudes entre sitios. Para usar esta función, llame al método AntiForgeryToken desde un formulario y agregue el atributo ValidateAntiForgeryTokenAttribute al método de acción que desea proteger.

Genera un campo de formulario oculto (token anti-falsificación) que se valida cuando se envía el formulario.

Sintaxis

  • @ Html.AntiForgeryToken ()

Observaciones

Al enviar una solicitud ajax con el token CSRF ( __RequestVerificationToken ), asegúrese de que el tipo de contenido no esté establecido en application/json . Si está utilizando jQuery, automáticamente establece el tipo de contenido en application/x-www-form-urlencoded que luego es reconocido por ASP.NET MVC.

Precaución

Tenga cuidado al establecer este valor. Su uso inadecuado puede abrir vulnerabilidades de seguridad en la aplicación.

Uso básico

El método de ayuda @Html.AntiForgeryToken() protege contra ataques de falsificación de solicitudes entre sitios (o CSRF).

Se puede usar simplemente usando el ayudante Html.AntiForgeryToken() dentro de uno de sus formularios existentes y decorando su Acción de controlador correspondiente con el atributo [ValidateAntiForgeryToken] .

Maquinilla de afeitar (YourView.cshtml)

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

O

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

Controlador (YourController.cs)

El método de acción objetivo:

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

Deshabilitar el control heurístico de identidad

Muchas veces verá una excepción

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

Esto se debe a que el token de Anti-falsificación también está vinculado al usuario que ha iniciado sesión actualmente. Este error aparece cuando un usuario inicia sesión pero su token sigue vinculado a ser un usuario anónimo para el sitio.

Hay algunas formas de solucionar este comportamiento, pero si prefiere no tener los tokens CSRF vinculados al estado de inicio de sesión de un usuario, puede desactivar esta función.

Coloque esta línea en su archivo Global.asax o en una lógica de inicio de aplicación similar.

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;

Validando todas las publicaciones

Debido a la vulnerabilidad causada por CSRF, generalmente se considera una buena práctica verificar un AntiForgeryToken en todos los HttpPosts, a menos que haya una buena razón para no hacerlo (algún problema técnico con la publicación, hay otro mecanismo de autenticación y / o el la publicación no muta el estado como guardarlo en un db o archivo). Para asegurarse de no olvidar, puede agregar un GlobalActionFilter especial que verifique automáticamente todos los HttpPosts a menos que la acción esté decorada con un atributo especial de "ignorar".

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

Para asegurarse de que se verifique en todas las solicitudes, solo agréguelo a sus filtros de acción global

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

Uso anticipado: aplique el filtro antiforgery predeterminado para cada POST

Podemos olvidar aplicar el Antiforgery attribute para cada solicitud POST por lo que deberíamos hacerlo por defecto. Esta muestra asegurará que el Antiforgery filter siempre se aplique a cada solicitud POST .

Primero crea un nuevo filtro 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;
    }
}

Luego registre este filtro personalizado a 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);
    }
}

Por lo tanto, ahora todas sus solicitudes POST están protegidas de forma predeterminada mediante los atributos de Antiforgery, por lo que ya no necesitamos tener el atributo [ValidateAntiForgeryToken] en cada método POST.

Uso de AntiForgeryToken con la solicitud de Ajax de Jquery

Primero creas el formulario

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

Método de acción

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

Guión

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

Asegúrese de que contentType no esté configurado para nada aparte de application/x-www-form-urlencoded y si Jquery no está especificado por defecto es application/x-www-form-urlencoded



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow