WebForms 应用程序中的 ValidateAntiForgeryToken

ValidateAntiForgeryToken in WebForms Application

我阅读了一些有关使用 ValidateAntiForgeryToken 来防止 XSRF/CSRF 攻击的文章。然而,我所看到的似乎只与 MVC 有关。

这些是我看过的文章:

ValidateAntiForgeryToken purpose, explanation and example

CSRF and AntiForgeryToken

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

如何在 WebForms 应用程序中实现这个或类似的东西?

CSRF 攻击并不仅仅针对 MVC 应用程序,Web 表单也很容易受到攻击。

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

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

你可以找到详细的解释here

为了保护您的 webforms 应用程序免受 CSRF 攻击(它在我的项目中有效),就是在您的母版页中实现它,如下所示:

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

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>

希望您会发现这很有用。

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

这是操作方法...

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

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

我找到了这篇文章 How To Fix Cross-Site Request Forgery (CSRF) using Microsoft .Net ViewStateUserKey and Double Submit Cookie,其中包含以下信息代码和说明:

Starting with Visual Studio 2012, Microsoft added built-in CSRF protection to new web forms application projects. To utilize this code, add a new ASP .NET Web Forms Application to your solution and view the Site.Master code behind page. This solution will apply CSRF protection to all content pages that inherit from the Site.Master page.

The following requirements must be met for this solution to work:

•All web forms making data modifications must use the Site.Master page.

•All requests making data modifications must use the ViewState.

•The web site must be free from all Cross-Site Scripting (XSS) vulnerabilities. See how to fix Cross-Site Scripting (XSS) using Microsoft .Net Web Protection Library for details.

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.");
        }
    }
}

}