Использование MVC HtmlHelper от WebForm

Свойства Symantically являются атрибутами Ваших объектов. Методы являются поведениями Вашего объекта.

Маркировка является атрибутом, и имеет больше смысла делать это свойством.

С точки зрения Объектно-ориентированного программирования у Вас должно быть ясное понимание того, что является частью поведения и что является просто атрибутом.

Автомобиль {Цвет, Модель, Бренд}

автомобиль А имеет Цвет, Модель и атрибуты Бренда поэтому, не имеет смысла иметь метод SetColor или SetModel, потому что symantically мы не просим, чтобы Автомобиль выбрал свой собственный цвет.

Поэтому, если Вы отображаете случай свойства/метода на реальный объект или смотрите на него от symantic точки наблюдения, Ваш беспорядок действительно уйдет.

18
задан Community 23 May 2017 в 12:15
поделиться

3 ответа

Ключевой метод находится в исходном коде MVC: GetAntiForgeryTokenAndSetCookie

Это создает экземпляр внутреннего запечатанного класса с именем AntiForgeryData .

Экземпляр сериализуется в файл cookie «__RequestVerificationToken_» + версию пути приложения в кодировке base 64.

Тот же экземпляр AntiForgeryData сериализуется в скрытый ввод.

Уникальная часть AntiForgeryData получена с помощью RNGCryptoServiceProvider.GetBytes ()

Все это можно подделать на странице WebForms, единственный беспорядочный бит - это сериализация скрытый запечатанный класс.К сожалению, ключевой метод ( GetAntiForgeryTokenAndSetCookie ) полагается на ViewContext.HttpContext.Request для получения файлов cookie, тогда как WebForm необходимо использовать HttpContext.Current.Request вместо .


Обновление

Не много тестирования и много кода, но я думаю, что исправил это с помощью небольшого размышления. Там, где я использовал отражение, я оставил эквивалентную строку закомментированной выше:

using System;
using System.Reflection;
using System.Web;
using System.Web.Mvc;

/// <summary>Utility to provide MVC anti forgery tokens in WebForms pages</summary>
public class WebFormAntiForgery
{
    /// <summary>Create an anti forgery token in a WebForms page</summary>
    /// <returns>The HTML input and sets the cookie</returns>
    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;
    }
}

Тогда использование аналогично MVC:

WebFormAntiForgery.AntiForgeryToken()

Он создает тот же файл cookie и тот же HTML-код, что и методы MVC.

Я не стал беспокоиться о методах соли и домена, но их довольно легко добавить.

6
ответ дан 30 November 2019 в 08:21
поделиться

you could create a new HtmlHelper in your controller and then pull the anti xrsf from there:

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);
0
ответ дан 30 November 2019 в 08:21
поделиться

По умолчанию веб-формы ASP.NET уже включают меры для проверки событий и состояния просмотра. Фил Хаак немного рассказывает об этом в связанном посте. Стратегии защиты от XSRF обсуждаются здесь (Скотт Хансельман) и здесь (Дино Эспозито)

1
ответ дан 30 November 2019 в 08:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: