【问题标题】:ValidateAntiForgeryToken in WebForms ApplicationValidateAntiForgeryToken 在 WebForms 应用程序中
【发布时间】:2018-09-13 13:52:20
【问题描述】:

我已经阅读了一些关于使用ValidateAntiForgeryToken 来防止 XSRF/CSRF 攻击的信息。但是我所看到的似乎只与 MVC 有关。

这些是我看过的文章:

ValidateAntiForgeryToken purpose, explanation and example

CSRF and AntiForgeryToken

XSRF/CSRF Prevention in ASP.NET MVC and Web Pages

如何在 WebForms 应用程序中实现此功能或类似功能?

【问题讨论】:

    标签: c# asp.net webforms csrf-protection


    【解决方案1】:

    CSRF 攻击不仅限于 MVC 应用程序,Web 表单也容易受到攻击。

    基本上,CSRF 攻击利用网站在用户浏览器中的信任,通常通过恶意网站中的隐藏表单或 JavaScript XMLHttpRequests 向网站请求或发布信息,因为用户使用存储在浏览器中的 cookie。

    为了防止这种攻击,您需要一个防伪令牌,一个在您的表单中发送的唯一令牌,您需要在信任表单信息之前对其进行验证。

    你可以找到详细的解释here

    要保护您的网络表单应用免受 CSRF 攻击(它在我的项目中有效),就是在您的母版页中实现它,如下所示:

    添加将为您处理 CSRF 验证的新类:

    public class CsrfHandler
    {
        public static void Validate(Page page, HiddenField forgeryToken)
        {
            if (!page.IsPostBack)
            {
                Guid antiforgeryToken = Guid.NewGuid();
                page.Session["AntiforgeryToken"] = antiforgeryToken;
                forgeryToken.Value = antiforgeryToken.ToString();
            }
            else
            {
                Guid stored = (Guid)page.Session["AntiforgeryToken"];
                Guid sent = new Guid(forgeryToken.Value);
                if (sent != stored)
                {
                    // you can throw an exception, in my case I'm just logging the user out
                    page.Session.Abandon();
                    page.Response.Redirect("~/Default.aspx");
                }
            }
        }
    }
    

    然后在您的母版页中实现它:

    MyMasterPage.Master.cs:

    protected void Page_Load(object sender, EventArgs e)
    {
        CsrfHandler.Validate(this.Page, forgeryToken);
        ...
    }
    

    MyMaster.Master:

    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:HiddenField ID="forgeryToken" runat="server"/>
        ...
    </form>
    

    希望您会发现这很有用。

    【讨论】:

      【解决方案2】:

      我发现这篇文章How To Fix Cross-Site Request Forgery (CSRF) using Microsoft .Net ViewStateUserKey and Double Submit Cookie有以下信息代码和说明:

      从 Visual Studio 2012 开始,Microsoft 为新的 Web 表单应用程序项目添加了内置的 CSRF 保护。要使用此代码,请将新的 ASP .NET Web 窗体应用程序添加到您的解决方案并查看 Site.Master 代码隐藏页面。此解决方案将对所有从 Site.Master 页面继承的内容页面应用 CSRF 保护。

      此解决方案必须满足以下要求:

      •所有进行数据修改的 Web 表单都必须使用 Site.Master 页面。

      •所有进行数据修改的请求都必须使用 ViewState。

      •网站必须没有任何跨站脚本 (XSS) 漏洞。详情请见how to fix Cross-Site Scripting (XSS) using Microsoft .Net Web Protection Library

      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)
      {
          //First, check for the existence of the Anti-XSS cookie
          var requestCookie = Request.Cookies[AntiXsrfTokenKey];
          Guid requestCookieGuidValue;
      
          //If the CSRF cookie is found, parse the token from the cookie.
          //Then, set the global page variable and view state user
          //key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad
          //method.
          if (requestCookie != null
          && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
          {
              //Set the global token variable so the cookie value can be
              //validated against the value in the view state form field in
              //the Page.PreLoad method.
              _antiXsrfTokenValue = requestCookie.Value;
      
              //Set the view state user key, which will be validated by the
              //framework during each request
              Page.ViewStateUserKey = _antiXsrfTokenValue;
          }
          //If the CSRF cookie is not found, then this is a new session.
          else
          {
              //Generate a new Anti-XSRF token
              _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
      
              //Set the view state user key, which will be validated by the
              //framework during each request
              Page.ViewStateUserKey = _antiXsrfTokenValue;
      
              //Create the non-persistent CSRF cookie
              var responseCookie = new HttpCookie(AntiXsrfTokenKey)
              {
                  //Set the HttpOnly property to prevent the cookie from
                  //being accessed by client side script
                  HttpOnly = true,
      
                  //Add the Anti-XSRF token to the cookie value
                  Value = _antiXsrfTokenValue
              };
      
              //If we are using SSL, the cookie should be set to secure to
              //prevent it from being sent over HTTP connections
              if (FormsAuthentication.RequireSSL &&
              Request.IsSecureConnection)
              responseCookie.Secure = true;
      
              //Add the CSRF cookie to the response
              Response.Cookies.Set(responseCookie);
          }
      
              Page.PreLoad += master_Page_PreLoad;
          }
      
          protected void master_Page_PreLoad(object sender, EventArgs e)
          {
              //During the initial page load, add the Anti-XSRF token and user
              //name to the ViewState
              if (!IsPostBack)
              {
                  //Set Anti-XSRF token
                  ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
      
                  //If a user name is assigned, set the user name
                  ViewState[AntiXsrfUserNameKey] =
                  Context.User.Identity.Name ?? String.Empty;
              }
              //During all subsequent post backs to the page, the token value from
              //the cookie should be validated against the token in the view state
              //form field. Additionally user name should be compared to the
              //authenticated users name
              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.");
              }
          }
      }
      

      }

      【讨论】:

      • 这种方法的优点是不使用Session对象。如果您正在开发需要在多台服务器上运行的应用程序,则在服务器端保留状态会阻止您在服务器之间分配负载。
      【解决方案3】:

      使用 WebForms,最好的办法是利用 ViewStateUserKey

      这是怎么做的......

      void Page_Init(object sender, EventArgs args)
      {    
          ViewStateUserKey = (string)(Session["SessionID"] = Session.SessionID);
      }
      

      SessionID 保存在会话变量中似乎有点奇怪,但这是必需的,因为它会在为空时自动生成一个新 ID。

      【讨论】:

        猜你喜欢
        • 2019-04-28
        • 2011-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        • 2020-03-07
        • 2015-11-07
        相关资源
        最近更新 更多