【问题标题】:Generating AntiForgeryToken in WebForms在 WebForms 中生成 AntiForgeryToken
【发布时间】:2010-11-22 05:34:59
【问题描述】:

我有一个 .NET Webforms 站点,感谢需要发布到我的 MVC 应用程序,该应用程序当前作为单独的应用程序位于 Webform 站点内。

Webform 应用程序需要向 MVC 应用程序 POST 一些敏感值。

有没有办法在我的 WebForms 应用程序中生成 AntiForgeryToken() 以便它可以与表单发布一起传递。

否则,是否有人知道任何其他自定义防伪代码可以让我执行类似于 MVC 的 AntiForgeryValidation 的操作。

【问题讨论】:

    标签: asp.net-mvc xss


    【解决方案1】:

    自己实现并不难。

    • 生成 GUID
    • 把它放在一个隐藏的字段中
    • 同样放在Session或Cookie中(后一种情况,有一些防篡改保护)
    • 在开始处理表单时,比较字段和存储的令牌。

    (如果你看一下 MVC 的实现,它几乎没有更多的东西。你只需要一些帮助方法。)

    【讨论】:

    【解决方案2】:

    这是一个老问题,但用于 Web 表单的最新 Visual Studio 2012 ASP.NET 模板包含嵌入母版页的反 CSRF 代码。如果您没有模板,下面是它生成的代码:

    Protected Sub Page_Init(sender As Object, e As System.EventArgs)
    
    
        ' The code below helps to protect against XSRF attacks
        Dim requestCookie As HttpCookie = Request.Cookies(AntiXsrfTokenKey)
        Dim requestCookieGuidValue As Guid
        If ((Not requestCookie Is Nothing) AndAlso Guid.TryParse(requestCookie.Value, requestCookieGuidValue)) Then
            ' Use the Anti-XSRF token from the cookie
            _antiXsrfTokenValue = requestCookie.Value
            Page.ViewStateUserKey = _antiXsrfTokenValue
        Else
            ' Generate a new Anti-XSRF token and save to the cookie
            _antiXsrfTokenValue = Guid.NewGuid().ToString("N")
            Page.ViewStateUserKey = _antiXsrfTokenValue
    
            Dim responseCookie As HttpCookie = New HttpCookie(AntiXsrfTokenKey) With {.HttpOnly = True, .Value = _antiXsrfTokenValue}
            If (FormsAuthentication.RequireSSL And Request.IsSecureConnection) Then
                responseCookie.Secure = True
            End If
            Response.Cookies.Set(responseCookie)
        End If
    
        AddHandler Page.PreLoad, AddressOf master_Page_PreLoad
    End Sub
    
    Private Sub master_Page_PreLoad(sender As Object, e As System.EventArgs)
    
    
        If (Not IsPostBack) Then
            ' Set Anti-XSRF token
            ViewState(AntiXsrfTokenKey) = Page.ViewStateUserKey
            ViewState(AntiXsrfUserNameKey) = If(Context.User.Identity.Name, String.Empty)
        Else
            ' Validate the Anti-XSRF token
            If (Not DirectCast(ViewState(AntiXsrfTokenKey), String) = _antiXsrfTokenValue _
                Or Not DirectCast(ViewState(AntiXsrfUserNameKey), String) = If(Context.User.Identity.Name, String.Empty)) Then
                Throw New InvalidOperationException("Validation of Anti-XSRF token failed.")
            End If
        End If
    End Sub
    

    【讨论】:

    • 出色的帖子,但您错过了声明 AntiXsrfTokenKeyAntiXsrfUserNameKey_antiXsrfTokenValue 的 3 行。可能对某些人有用:-)
    • @IanIppolito 此代码是否会验证直接发送至处理程序的请求?因为当时我认为这段代码不会被执行。
    • 您好先生,我正在使用 VS2013 和 .Net FrameWork 4.5 创建我的 ASP.net Web 表单应用程序,但我的母版页不包含此自动生成的代码,我如何知道我的网站是否是远离 CSRF 吗?
    • 你能提供这个自动生成代码的C#版本吗?
    【解决方案3】:

    Ian Ippolito 的 C# 版本在这里回答:

    public partial class SiteMaster : MasterPage
    {
        private const string AntiXsrfTokenKey = "__AntiXsrfToken";
        private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
        private string _antiXsrfTokenValue;
    
        protected void Page_Init(object sender, EventArgs e)
        {
            // The code below helps to protect against XSRF attacks
            var requestCookie = Request.Cookies[AntiXsrfTokenKey];
            Guid requestCookieGuidValue;
            if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
            {
                // Use the Anti-XSRF token from the cookie
                _antiXsrfTokenValue = requestCookie.Value;
                Page.ViewStateUserKey = _antiXsrfTokenValue;
            }
            else
            {
                // Generate a new Anti-XSRF token and save to the cookie
                _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
                Page.ViewStateUserKey = _antiXsrfTokenValue;
    
                var responseCookie = new HttpCookie(AntiXsrfTokenKey)
                {
                    HttpOnly = true,
                    Value = _antiXsrfTokenValue
                };
                if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
                {
                    responseCookie.Secure = true;
                }
                Response.Cookies.Set(responseCookie);
            }
    
            Page.PreLoad += master_Page_PreLoad;
        }
    
        protected void master_Page_PreLoad(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Set Anti-XSRF token
                ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
                ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
            }
            else
            {
                // Validate the Anti-XSRF token
                if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                    || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
                {
                    throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
                }
            }
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    }
    

    【讨论】:

    • 是否有必要使用上下文中的用户身份进行验证?当 Context 在页面之间继续时,视图状态将保持为该页面的状态。如果在运行验证时身份更改(通过使用多个选项卡浏览),它将引发异常,因为 ViewState 不会更改。
    【解决方案4】:

    WebForms 在Page.ViewStateUserKey 中有一个非常相似的类比。通过setting that to a per-user value(大多数选择HttpSessionState.SessionId),WebForms 将验证 ViewState1 作为the MAC check 的一部分。

     overrides OnInit(EventArgs e) {
         base.OnInit(e);
         ViewStateUserKey = Session.SessionId;
     }
    

    1 在某些情况下ViewStateUserKey will not help。主要是,他们归结为使用 GET 请求(或在没有检查 IsPostback 的情况下在 Page_Load 中)做危险的事情,或禁用 ViewStateMAC。

    【讨论】:

      【解决方案5】:

      您可以使用反射来获取用于设置 cookie 的 MVC 方法以及用于 MVC 验证的匹配表单输入。这样,您就可以拥有一个带有 [AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken] 属性的 MVC 操作,您可以从 WebForms 生成的页面发布到该操作。

      看到这个答案:Using an MVC HtmlHelper from a WebForm

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-13
        • 2012-01-31
        相关资源
        最近更新 更多