19

ハイブリッドWebForms/MVCサイトにいくつかのUI機能を追加しているところです。この場合、いくつかのAJAX UI機能を(jQueryを介して)WebFormsページに追加しており、データはMVCJsonResultから取得されています。1つの例外を除いて、すべてが100%機能しています。

AntiForgeryTokenのXSRF保護を実装したいと思います。純粋なMVCアプリケーションでValidateAntiForgeryToken属性と組み合わせて使用​​しましたが、WebFormsでHtml.AntiForgeryToken()メソッドを実装する方法を知りたいです。 UrlHelperを使用した例を次に示します。

ViewContext/RequestContextを正しく「モックアップ」するのに問題があります。WebFormsページ内でHtmlHelpersを使用するにはどうすればよいですか?

編集:MVC JsonResultからではなく、WebFormsページからAntiForgeryTokenを取得しようとしています。

4

4 に答える 4

21

これは古い質問ですが、今日この問題に遭遇し、共有したいと思いました。私はMVC4で作業しており、MVC(RenderPartial経由)とWebFormsの両方で共有されるWebフォームコントロール(.ascx)を持っています。そのコントロールでは、偽造防止トークンが必要でした。幸いなことに、Webフォームで使用できるヘルパーがあります。これは次のように簡単です。

<%= AntiForgery.GetHtml() %>

これにより、MVCで取得するのと同じように偽造防止トークンがレンダリングされます。

これがMSリンクです。

于 2013-05-01T18:41:05.157 に答える
6

重要な方法はMVCソースコードにあります:GetAntiForgeryTokenAndSetCookie

これにより、と呼ばれる内部の封印されたクラスのインスタンスが作成されAntiForgeryDataます。

インスタンスは、Cookie"__RequestVerificationToken_"+ベース64でエンコードされたバージョンのアプリケーションパスにシリアル化されます。

の同じインスタンスがAntiForgeryData非表示の入力にシリアル化されます。

のユニークな部分AntiForgeryDataRNGCryptoServiceProvider.GetBytes()

これらすべてがWebFormsページでスプーフィングされる可能性がありますが、厄介なのは、隠された封印されたクラスのシリアル化だけです。残念ながら、キーメソッド(GetAntiForgeryTokenAndSetCookie)はCookieを取得するために依存しViewContext.HttpContext.Requestていますが、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()

MVCメソッドと同じCookieと同じHTMLを作成します。

私はsaltとdomainの方法を気にしませんでしたが、それらを追加するのはかなり簡単でしょう。

于 2010-03-31T14:06:14.443 に答える
1

既定では、ASP.NET WebFormsには、イベントとビューステートを検証するためのメジャーが既に含まれています。Phil Haackは、リンクされた投稿でそれについて少し話します。XSRF緩和戦略については、ここ(Scott Hanselman)ここ(Dino Esposito)で説明されています。

于 2009-09-04T17:08:43.317 に答える
0

コントローラに新しい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);
于 2009-08-28T16:29:22.980 に答える