asp.net-mvc
Html.AntiForgeryToken
Sök…
Introduktion
Anti-forgery-tokenet kan användas för att skydda din ansökan mot förfalskning på olika platser. För att använda den här funktionen, anropa AntiForgeryToken-metoden från ett formulär och lägg till ValidateAntiForgeryTokenAttribute-attributet till åtgärdsmetoden som du vill skydda.
Genererar ett doldt formulärfält (anti-forgery token) som valideras när formuläret skickas in.
Syntax
- @ Html.AntiForgeryToken ()
Anmärkningar
När du skickar in en ajaxbegäran med CSRF-token ( __RequestVerificationToken
), se till att innehållstypen inte är inställd på application/json
. Om du använder jQuery ställer den automatiskt in innehållstypen till application/x-www-form-urlencoded
som sedan identifieras av ASP.NET MVC.
Varning
Var försiktig när du ställer in detta värde. Att använda det felaktigt kan öppna säkerhetsproblem i applikationen.
Grundläggande användning
Den @Html.AntiForgeryToken()
hjälpare metod skyddar mot cross-site begäran förfalskning (eller CSRF) attacker.
Det kan användas genom att helt enkelt använda Html.AntiForgeryToken()
-hjälpen i en av dina befintliga former och dekorera dess motsvarande Controller Action med attributet [ValidateAntiForgeryToken]
.
Razor (YourView.cshtml)
@using (Html.BeginForm("Manage", "Account")) {
@Html.AntiForgeryToken()
<!-- ... -->
}
ELLER
<form>
@Html.AntiForgeryToken()
<!-- ... -->
</form>
Controller (YourController.cs)
Målåtgärdsmetoden:
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult ActionMethod(ModelObject model)
{
// ...
}
Inaktivera identitetsheuristisk kontroll
Ofta ser du ett undantag
Anti forgery token is meant for user "" but the current user is "username"
Detta beror på att Anti-Forgery-tokenet också är länkat till den nuvarande inloggade användaren. Det här felet visas när en användare loggar in men deras token är fortfarande kopplad till att vara en anonym användare för webbplatsen.
Det finns några sätt att fixa detta beteende, men om du hellre inte vill ha CSRF-token länkade till ett användares inloggade tillstånd kan du inaktivera den här funktionen.
Lägg denna rad i din Global.asax
fil eller liknande applikationsstartlogik.
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
Validera alla inlägg
På grund av sårbarheten orsakad av CSRF anses det vanligtvis vara en bra praxis att kontrollera om det finns en AntiForgeryToken på alla HttpPosts såvida det inte finns en god anledning att inte göra det (något tekniskt problem med inlägget, det finns en annan autentiseringsmekanism och / eller inlägget muterar inte tillstånd som att spara till en db eller fil). För att säkerställa att du inte glömmer kan du lägga till ett speciell GlobalActionFilter som automatiskt kontrollerar alla HttpPosts såvida inte åtgärden är dekorerad med ett speciellt "ignorera" -attribut.
[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 { }
För att se till att det kontrolleras på alla förfrågningar, lägg bara till det i dina Global Action Filters
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//...
filters.Add(new ValidateAntiForgeryTokenOnAllPosts());
//...
}
}
Avancerad användning: Använd standard Antiforgery-filter för varje POST
Vi kan glömma att tillämpa Antiforgery attribute
för varje POST
begäran så vi ska göra det som standard. Detta prov säkerställer att Antiforgery filter
alltid tillämpas på varje POST
begäran.
AntiForgeryTokenFilter
nytt AntiForgeryTokenFilter
filter:
//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;
}
}
Registrera sedan detta anpassade filter till 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);
}
}
Så nu är alla dina POST
förfrågningar som standard skyddade med Antiforgery-attribut så vi behöver inte längre ha [ValidateAntiForgeryToken]
-attribut på varje POST-metod.
Använda AntiForgeryToken med Jquery Ajax Begäran
Först skapar du formuläret
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
Åtgärdsmetod
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(FormViewModel formData)
{
// ...
}
Manus
<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>
Se till att contentType inte är inställt på något annat än application/x-www-form-urlencoded
och om dess inte angivna Jquery är standardvärden för application/x-www-form-urlencoded