Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 从Web表单使用MVC HtmlHelper_Asp.net Mvc_Webforms_Html Helper - Fatal编程技术网

Asp.net mvc 从Web表单使用MVC HtmlHelper

Asp.net mvc 从Web表单使用MVC HtmlHelper,asp.net-mvc,webforms,html-helper,Asp.net Mvc,Webforms,Html Helper,我正在向混合WebForms/MVC站点添加一些UI功能。在本例中,我将向WebForms页面添加一些AJAX UI特性(通过jQuery),数据来自MVC JsonResult。一切正常,但有一个例外: 我想实现AntiForgeryToken的XSRF保护。我在纯MVC应用程序中结合使用了ValidateAntiForgeryToken属性,但想知道如何在WebForms中实现Html.AntiForgeryToken()方法 我在正确地“模拟”ViewContext/RequestCont

我正在向混合WebForms/MVC站点添加一些UI功能。在本例中,我将向WebForms页面添加一些AJAX UI特性(通过jQuery),数据来自MVC JsonResult。一切正常,但有一个例外:

我想实现AntiForgeryToken的XSRF保护。我在纯MVC应用程序中结合使用了ValidateAntiForgeryToken属性,但想知道如何在WebForms中实现Html.AntiForgeryToken()方法

我在正确地“模拟”ViewContext/RequestContext时遇到一些问题。我应该如何在WebForms页面中使用HtmlHelpers

编辑
我希望从我的WebForms页面检索AntiForgeryToken,而不是从MVC JsonResult中检索。

您可以在控制器中创建一个新的HtmlHelper,然后从那里提取反xrsf:

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

默认情况下,ASP.NET WebForms已经包含验证事件和viewstate的措施。在链接的帖子里谈了一点。讨论了XSRF缓解策略,关键方法在MVC源代码中:
GetAntiForgeryTokenAndSetCookie

这将创建名为
AntiForgeryData
的内部密封类的实例

实例被序列化为cookie“\uuuu RequestVerificationToken”+应用程序路径的基本64编码版本

AntiForgeryData
的同一实例被序列化为隐藏输入

通过
RNGCryptoServiceProvider.GetBytes()

所有这些都可能在WebForms页面中被欺骗,唯一混乱的是隐藏的密封类的序列化。不幸的是,关键方法(
GetAntiForgeryTokenAndSetCookie
)依赖于
ViewContext.HttpContext.Request
获取Cookie,而Web表单需要使用
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方法相同的cookie和HTML


我没有为salt和domain方法烦恼,但它们很容易添加。

我知道这是一个老问题,但今天我遇到了这个问题,我想与大家分享一下。我在MVC4中工作,有一个webform控件(.ascx),它在MVC(通过RenderPartial)和WebForms之间共享。在那个对照组中,我需要一个防伪令牌。幸运的是,现在您可以在webforms中使用一个助手,它非常简单:

<%= AntiForgery.GetHtml() %>

这将使您的防伪令牌像在MVC中一样


.

据我所知,AntiForgeryToken设置了一个cookie,并注入了一个隐藏的表单字段,因此可以对两者进行比较。这是如何实现的?非常好的链接,谢谢。我希望找到一种专门使用AntiForgeryToken的方法,因为MVC web服务的“消费者”位于WebForms页面上(我不会在MVC中重写)。我也有同样的问题-一个遗留WebForms页面需要使用
AntiForgeryToken
发布到MVC操作。我想将
Html.AntiForgeryToken()
添加到WebForms页面,而不在MVC中重写它。您好,我刚刚尝试在WebForms应用程序(.NET 4.0,MVC 3.0)中实现这一点,并从这一行中得到一个“对象引用未设置为对象实例”错误:var serializerCtor=serializerType.GetConstructor(新类型[0]);有人能帮忙吗?我在这里有点不知所措。@BFOT这是在ASP.NET2、MVC1上写的,完全是一种黑客行为——我在思考他们的防伪令牌内容,但这都是私有方法。很可能这需要对ASP和MVC的每个新版本进行更新,下载MVC 3源代码,看看这些方法是如何改变的-如果我们很幸运的话,他们甚至可能已经公开了它们,以便WebForms可以使用它们。感谢您的回复。这个周末我将看一看最新的MVC源代码,看看我是否能解决这个问题。如果有空,请随时发布上述代码的修订版本。;)看我的帖子;有一个新的受支持的帮助程序,您可以使用它来获取webforms页面中的功能。@BFOT@pvanhuten在MVC3中有一个更好的方法,现在内置了一个完全受支持的
AntiForgery.GetHtml()
方法。我的解决方案是一个仅适用于MVC1-2的垫片。非常好,这是解决WebForms 2/MVC 3及更高版本中问题的更好方法。
<%= AntiForgery.GetHtml() %>