我想要更新一个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()