Usar un MVC HtmlHelper desde un WebForm

Estoy en proceso de agregar algunas funcionalidades de UI a un sitio híbrido de WebForms / MVC. En este caso, estoy agregando algunas características AJAX UI a una página de WebForms (a través de jQuery), y los datos provienen de un MVC JsonResult. Todo funciona al 100%, con una excepción:

Me gustaría implementar la protección XSRF de AntiForgeryToken. Lo he usado en combinación con el atributo ValidateAntiForgeryToken en mis aplicaciones MVC puros, pero me gustaría saber cómo implementar el método Html.AntiForgeryToken () en WebForms. Aquí hay un ejemplo usando un UrlHelper .

Estoy teniendo problemas para “mockear” correctamente ViewContext / RequestContext. ¿Cómo debo usar HtmlHelpers en una página de WebForms?

Editar : Estoy buscando recuperar AntiForgeryToken desde mi página WebForms, no desde MVC JsonResult.

El método clave está en el código fuente de MVC: GetAntiForgeryTokenAndSetCookie

Esto crea una instancia de una clase interna sellada llamada AntiForgeryData .

La instancia se serializa en una cookie “__RequestVerificationToken_” + una versión codificada en base 64 de la ruta de la aplicación.

La misma instancia de AntiForgeryData se serializa en una entrada oculta.

La parte única de AntiForgeryData se obtiene con un RNGCryptoServiceProvider.GetBytes()

Todo esto podría ser falsificado en una página de WebForms, el único problema es la serialización de la clase sellada oculta. Lamentablemente, el método clave ( GetAntiForgeryTokenAndSetCookie ) se basa en ViewContext.HttpContext.Request para obtener las cookies, mientras que WebForm necesita utilizar HttpContext.Current.Request lugar.


Actualizar

No hay muchas pruebas y mucho código, pero creo que lo he descifrado con un pequeño reflection. Donde he usado la reflexión, he dejado la línea equivalente comentada arriba:

 using System; using System.Reflection; using System.Web; using System.Web.Mvc; /// Utility to provide MVC anti forgery tokens in WebForms pages public class WebFormAntiForgery { /// Create an anti forgery token in a WebForms page /// The HTML input and sets the cookie public static string AntiForgeryToken() { string formValue = GetAntiForgeryTokenAndSetCookie(); // string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null); var mvcAssembly = typeof(HtmlHelper).Assembly; var afdType = mvcAssembly.GetType("System.Web.Mvc.AntiForgeryData"); string fieldName = Convert.ToString(afdType.InvokeMember( "GetAntiForgeryTokenName", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { null })); TagBuilder builder = new TagBuilder("input"); builder.Attributes["type"] = "hidden"; builder.Attributes["name"] = fieldName; builder.Attributes["value"] = formValue; return builder.ToString(TagRenderMode.SelfClosing); } static string GetAntiForgeryTokenAndSetCookie() { var mvcAssembly = typeof(HtmlHelper).Assembly; var afdType = mvcAssembly.GetType("System.Web.Mvc.AntiForgeryData"); // new AntiForgeryDataSerializer(); var serializerType = mvcAssembly.GetType("System.Web.Mvc.AntiForgeryDataSerializer"); var serializerCtor = serializerType.GetConstructor(new Type[0]); object serializer = serializerCtor.Invoke(new object[0]); // string cookieName = AntiForgeryData.GetAntiForgeryTokenName(HttpContext.Current.Request.ApplicationPath); string cookieName = Convert.ToString(afdType.InvokeMember( "GetAntiForgeryTokenName", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { HttpContext.Current.Request.ApplicationPath })); // AntiForgeryData cookieToken; object cookieToken; HttpCookie cookie = HttpContext.Current.Request.Cookies[cookieName]; if (cookie != null) { // cookieToken = Serializer.Deserialize(cookie.Value); cookieToken = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null, serializer, new object[] { cookie.Value }); } else { // cookieToken = AntiForgeryData.NewToken(); cookieToken = afdType.InvokeMember( "NewToken", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[0]); // string cookieValue = Serializer.Serialize(cookieToken); string cookieValue = Convert.ToString(serializerType.InvokeMember("Serialize", BindingFlags.InvokeMethod, null, serializer, new object[] { cookieToken })); var newCookie = new HttpCookie(cookieName, cookieValue) { HttpOnly = true }; HttpContext.Current.Response.Cookies.Set(newCookie); } // AntiForgeryData formToken = new AntiForgeryData(cookieToken) // { // CreationDate = DateTime.Now, // Salt = salt // }; var ctor = afdType.GetConstructor(new Type[] { afdType }); object formToken = ctor.Invoke(new object[] { cookieToken }); afdType.InvokeMember("CreationDate", BindingFlags.SetProperty, null, formToken, new object[] { DateTime.Now }); afdType.InvokeMember("Salt", BindingFlags.SetProperty, null, formToken, new object[] { null }); // string formValue = Serializer.Serialize(formToken); string formValue = Convert.ToString(serializerType.InvokeMember("Serialize", BindingFlags.InvokeMethod, null, serializer, new object[] { formToken })); return formValue; } } 

El uso es similar a MVC:

 WebFormAntiForgery.AntiForgeryToken() 

Crea la misma cookie y el mismo HTML que los métodos MVC.

No me he molestado con los métodos de sal y dominio, pero serían bastante fáciles de agregar.

Sé que esta es una vieja pregunta, pero me encontré con este problema hoy y pensé que lo compartiría. Estoy trabajando en MVC4 y tengo un control de formulario web (.ascx) que se comparte entre MVC (a través de RenderPartial) y WebForms. En ese control, necesitaba una ficha antiforgery. Afortunadamente, ahora hay un ayudante que puedes usar en tus formularios web, que es tan simple como esto:

 <%= AntiForgery.GetHtml() %> 

Esto hará que su token anti falsificación sea como la que obtendría en MVC.

Aquí está el enlace MS a él .

De forma predeterminada, ASP.NET WebForms ya incluye medidas para validar eventos y viewstate. Phil Haack habla un poco acerca de eso en la publicación vinculada. Aquí se habla de las estrategias de mitigación de XSRF (Scott Hanselman) y aquí (Dino Esposito)

puedes crear un nuevo HtmlHelper en tu controlador y luego extraer el anti xrsf desde allí:

 var htmlHelper = new HtmlHelper( new ViewContext( ControllerContext, new WebFormView("omg"), new ViewDataDictionary(), new TempDataDictionary()), new ViewPage()); var xsrf = htmlHeler.AntiForgeryToken; myObject.XsrfToken = xsrf; return JsonResult(myObject);