Ich musste ein wenig zwielichtig sein, um Anti-Fälschungs-Token beim Posten von JSON zu validieren, aber es funktionierte.
$.ajaxSetup({
beforeSend: function (xhr, options) {
if (options.type && options.type.toLowerCase() !== 'get' && typeof (options.data) === 'string' && options.url.indexOf("?__RequestVerificationToken=") < 0 && options.url.indexOf("&__RequestVerificationToken=") < 0) {
if (options.url.indexOf('?') < 0) {
options.url += '?';
}
else {
options.url += '&';
}
options.url += "__RequestVerificationToken=" + encodeURIComponent($('input[name=__RequestVerificationToken]').val());
}
}
});
Wie bereits erwähnt, überprüft die Validierung jedoch nur das Formular - nicht JSON und nicht die Abfragezeichenfolge. Also haben wir das Verhalten des Attributs überschrieben. Die erneute Implementierung der gesamten Validierung wäre schrecklich (und wahrscheinlich nicht sicher) gewesen. Daher habe ich die Form-Eigenschaft einfach überschrieben, um, wenn das Token im QueryString übergeben wurde, die integrierte Validierung THINK zu erhalten, die im Formular enthalten war.
Das ist etwas schwierig, da das Formular schreibgeschützt, aber machbar ist.
if (IsAuth(HttpContext.Current) && !IsGet(HttpContext.Current))
{
if (HttpContext.Current.Request.Params != null && HttpContext.Current.Request.Form != null
&& HttpContext.Current.Request.Params["__RequestVerificationToken"] != null && HttpContext.Current.Request.Form["__RequestVerificationToken"] == null)
{
AntiForgery.Validate(new ValidationHttpContextWrapper(HttpContext.Current), null);
}
else
{
AntiForgery.Validate(new HttpContextWrapper(HttpContext.Current), null);
}
}
private static bool IsAuth(HttpContext context)
{
return context.User != null && context.User.Identity != null && !string.IsNullOrEmpty(context.User.Identity.Name);
}
private static bool IsGet(HttpContext context)
{
return context.Request.HttpMethod.ToUpper() == "GET";
}
...
internal class ValidationHttpContextWrapper : HttpContextBase
{
private HttpContext _context;
private ValidationHttpRequestWrapper _request;
public ValidationHttpContextWrapper(HttpContext context)
: base()
{
_context = context;
_request = new ValidationHttpRequestWrapper(context.Request);
}
public override HttpRequestBase Request { get { return _request; } }
public override IPrincipal User
{
get { return _context.User; }
set { _context.User = value; }
}
}
internal class ValidationHttpRequestWrapper : HttpRequestBase
{
private HttpRequest _request;
private System.Collections.Specialized.NameValueCollection _form;
public ValidationHttpRequestWrapper(HttpRequest request)
: base()
{
_request = request;
_form = new System.Collections.Specialized.NameValueCollection(request.Form);
_form.Add("__RequestVerificationToken", request.Params["__RequestVerificationToken"]);
}
public override System.Collections.Specialized.NameValueCollection Form { get { return _form; } }
public override string ApplicationPath { get { return _request.ApplicationPath; } }
public override HttpCookieCollection Cookies { get { return _request.Cookies; } }
}
Es gibt noch einige andere Dinge, die an unserer Lösung anders sind (insbesondere verwenden wir ein HttpModule, damit wir nicht jedem einzelnen POST das Attribut hinzufügen müssen), die ich zugunsten der Kürze ausgelassen habe. Ich kann es bei Bedarf hinzufügen.
ValidateJsonAntiForgeryTokenAttribute
hingelegt?