加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 使用WebForm的MVC HtmlHelper

发布时间:2020-12-16 00:34:56 所属栏目:asp.Net 来源:网络整理
导读:我正在为混合WebForms / MVC网站添加一些UI功能。在这种情况下,我将一些AJAX UI功能添加到WebForms页面(通过jQuery),数据来自MVC JsonResult。一切都在100%工作,有一个例外: 我想实施XSRF保护AntiForgeryToken。我已经将它与我的纯MVC应用程序中的Valid
我正在为混合WebForms / MVC网站添加一些UI功能。在这种情况下,我将一些AJAX UI功能添加到WebForms页面(通过jQuery),数据来自MVC JsonResult。一切都在100%工作,有一个例外:

我想实施XSRF保护AntiForgeryToken。我已经将它与我的纯MVC应用程序中的ValidateAntiForgeryToken属性结合使用,但想知道如何在WebForms中实现Html.AntiForgeryToken()方法。 Here’s an example using a UrlHelper。

我正在让ViewContext / RequestContext“嘲笑”正确的一些麻烦。如何在WebForms页面中使用HtmlHelpers?

编辑:
我正在从我的WebForms页面检索AntiForgeryToken,而不是从MVC JsonResult中检索。

解决方法

关键的方法是在MVC源代码中:GetAntiForgeryTokenAndSetCookie

这将创建一个称为AntiForgeryData的内部密封类的实例。

该实例被序列化为一个基于应用程序路径的64位编码版本的cookie“__RequestVerificationToken_”。

相同的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,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",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,serializer,new object[] { cookie.Value });
        }
        else
        {
            // cookieToken = AntiForgeryData.NewToken();
            cookieToken = afdType.InvokeMember(
                "NewToken",BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod,new object[0]);

            // string cookieValue = Serializer.Serialize(cookieToken);
            string cookieValue = Convert.ToString(serializerType.InvokeMember("Serialize",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,formToken,new object[] { DateTime.Now });
        afdType.InvokeMember("Salt",new object[] { null });

        // string formValue = Serializer.Serialize(formToken);
        string formValue = Convert.ToString(serializerType.InvokeMember("Serialize",new object[] { formToken }));
        return formValue;
    }
}

用法类似于MVC:

WebFormAntiForgery.AntiForgeryToken()

它创建与MVC方法相同的cookie和相同的HTML。

我没有用盐和域方法打扰,但它们相当容易添加。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读