Utilizzo di MVC HtmlHelper da un WebForm

Sono in procinto di aggiungere alcune funzionalità dell’interfaccia utente a un sito WebForms / MVC ibrido. In questo caso, aggiungo alcune funzionalità di interfaccia utente AJAX a una pagina WebForms (tramite jQuery) e i dati provengono da un MVC JsonResult. Tutto funziona al 100%, con un’eccezione:

Vorrei implementare la protezione XSRF di AntiForgeryToken. L’ho usato in combinazione con l’attributo ValidateAntiForgeryToken sulle mie applicazioni MVC pure, ma vorrei sapere come implementare il metodo Html.AntiForgeryToken () in WebForms. Ecco un esempio usando un UrlHelper .

Sto avendo qualche problema a visualizzare ViewContext / RequestContext “mocked” correttamente. Come dovrei usare HtmlHelpers in una pagina WebForms?

Modifica : sto cercando di recuperare AntiForgeryToken dalla mia pagina WebForms, non da MVC JsonResult.

Il metodo chiave è nel codice sorgente MVC: GetAntiForgeryTokenAndSetCookie

Ciò crea un’istanza di una class chiusa interna denominata AntiForgeryData .

L’istanza è serializzata in un cookie “__RequestVerificationToken_” + una versione codificata base 64 del percorso dell’applicazione.

La stessa istanza di AntiForgeryData è serializzata in un input nascosto.

La parte unica di AntiForgeryData è ottenuta con un RNGCryptoServiceProvider.GetBytes()

Tutto ciò potrebbe essere spoofed in una pagina WebForms, l’unico bit disordinato è la serializzazione della class sealed nascosta. Sfortunatamente il metodo chiave ( GetAntiForgeryTokenAndSetCookie ) si basa su ViewContext.HttpContext.Request per accedere ai cookie, mentre il WebForm deve utilizzare HttpContext.Current.Request .


Aggiornare

Non molti test e tanto codice, ma penso di averlo risolto con una piccola riflessione. Dove ho usato la reflection ho lasciato la riga equivalente commentata sopra:

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

L’utilizzo è quindi simile a MVC:

 WebFormAntiForgery.AntiForgeryToken() 

Crea lo stesso cookie e lo stesso codice HTML dei metodi MVC.

Non mi sono preoccupato dei metodi salt e del dominio, ma sarebbero stati abbastanza facili da aggiungere.

So che questa è una vecchia domanda, ma oggi mi sono imbattuto in questo problema e ho pensato di condividerlo. Sto lavorando in MVC4 e ho un controllo webform (.ascx) condiviso tra MVC (tramite RenderPartial) e WebForms. In quel controllo, avevo bisogno di un token anti-contraffazione. Fortunatamente, ora c’è un aiuto che puoi usare nei tuoi webforms: semplice:

 <%= AntiForgery.GetHtml() %> 

Questo renderà il tuo token anti-contraffazione come se fossi in MVC.

Ecco il link MS ad esso .

Per impostazione predefinita, i WebForm di ASP.NET includono già misure per convalidare eventi e viewstate. Phil Haack ne parla un po ‘nel post collegato. Qui si parla di strategie di mitigazione XSRF (Scott Hanselman) e qui (Dino Esposito)

potresti creare un nuovo HtmlHelper nel tuo controller e poi tirare l’anti xrsf da lì:

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