在使用ajax时防止asp.net web应用程序中的CSRF



我想要更新一个asp web应用程序,以防止跨站点请求伪造攻击。

我使用了VS2012中Microsoft自动生成的代码,并将其添加到主页面中,如下所述。它运行得很好,但有一个页面通过AJAX请求将JSON发布到Web方法

我也想检查一下这个ajax请求。

可预见的问题是:

var responseCookie = new HttpCookie(AntiXsrfTokenKey)
   {
        //Set the HttpOnly property to prevent the cookie from
        //being accessed by client side script
                HttpOnly = true,

这显然是可以改变的,但这似乎会增加网站的漏洞。这是一个重大问题吗?

我可以通过ajax请求发送viewstate隐藏输入的值,但这需要被解码回键值对,以完成等效的操作:

(string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue 

有没有一种简单的方法可以使用现有的asp.net方法来做到这一点?

谢谢你的帮助。

以下是我的发现。正如geedubb所描述的,我最终使用了LosFormatter,在MasterPage中添加了以下代码,并将值分配给一个隐藏的输入,该输入随ajax请求返回。当我发布这个问题时,我没有意识到HttpCookie.HttpOnly属性仍然会在ajax请求上发布cookie,因此可以设置为false。

internal string GetToken()
{
    // call the static method to guarantee LosFormatter remains threadsafe
    return GetToken(_antiXsrfTokenValue); 
}
private static string GetCurrentUserName()
{
    var currentUser = HttpContext.Current.User.Identity;
    return (currentUser == null) ? string.Empty : currentUser.Name;
}
private static string GetToken(string token)
{
    var los = new System.Web.UI.LosFormatter(true, token);
    var writer = new System.IO.StringWriter();
    var data = new Dictionary<string,string>();
    data.Add("TokenValue",token);
    data.Add("UserNameKey", GetCurrentUserName());
    los.Serialize(writer, data);
    return writer.ToString();
}
internal static void Validate(string token)
{
    var request = HttpContext.Current.Request;
    var requestCookie = request.Cookies[AntiXsrfTokenKey];
    var antiXsrfTokenValue = requestCookie.Value;
    var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
    var xsrfData = (Dictionary<string,string>)los.Deserialize(token);
    if (xsrfData["TokenValue"] != antiXsrfTokenValue || xsrfData["UserNameKey"] != GetCurrentUserName())
    {
        throw new System.Security.Authentication.AuthenticationException("Validation of Anti-XSRF token failed.");
    }
}

最初,我尝试使用相同的代码发送_VIEWSTATE隐藏输入的值

       var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
       var ajaxViewState = los.Deserialize(token)

但这引发了一个错误,说明提供的密钥无法取消字符串的序列化。明显设置

       Page.ViewStateUserKey = _antiXsrfTokenValue;

具有比单独提供的密钥更复杂的密钥。如果有人知道如何使用userKey反序列化视图状态字符串,我会很感兴趣。

我提供的方法唯一的问题是返回的字符串的大小——对于GUID+6个字符的用户名,长度为1976个字符!!!!

如果再次遇到这个问题,我会引用System.Web.WebPages.dll(在mvc项目中使用),并使用与在mvc 中创建Html.AntiForgeryToken相同的方法

namespace System.Web.Helpers
{
    /// <summary>
    /// Provides access to the anti-forgery system, which provides protection against
    /// Cross-site Request Forgery (XSRF, also called CSRF) attacks.
    /// </summary>
    public static class AntiForgery
    {
        public static void GetTokens(string oldCookieToken, out string newCookieToken, out string formToken)
        public static void Validate()

最新更新