C#AntiForgeryToken属性导致mvc应用程序中的StackOverflowException

时间:2015-03-12 12:20:59

标签: c# jquery ajax asp.net-mvc stack-overflow

我创建了一个反伪造属性类来装饰我的GenericBaseController类:

[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

(参考链接http://richiban.uk/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

一旦应用程序中的正常POST调用完成(不是ajax),我总是得到StackOverflowException。 没有ValidateAntiForgeryTokenAttribute的应用程序运行正常。 如果我在这个类中调试代码,在发布请求之后,流程继续通过行

new ValidateAntiForgeryTokenAttribute()
    .OnAuthorization(filterContext);

无限。 链接文章中的人确保此实现有效,因此我想知道为什么我会遇到此问题。 当请求不是ajax时,它真的应该创建一个新的ValidateAntiForgeryTokenAttribute吗?

1 个答案:

答案 0 :(得分:1)

归结为问题,您的代码是:

public class ValidateAntiForgeryTokenAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if ( evaluateCondition() )
        {}
        else
        {
            new ValidateAntiForgeryTokenAttribute()
                .OnAuthorization(filterContext);
        }
    }
}

问题

您的电话在else区块中递归:

  • 您调用该方法的类是ValidateAntiForgeryTokenAttribute

  • 在您的else区块中

    new ValidateAntiForgeryTokenAttribute()
        .OnAuthorization(filterContext);
    

    ,鉴于调用方法是

    public override void OnAuthorization(AuthorizationContext filterContext)
    

    表示您将继续在OnAuthorization的新实例上调用ValidateAntiForgeryTokenAttribute(即相同的方法)。


<强>解决方案

在您发布的示例中,情况略有不同 - 类的名称为ValidateAntiForgeryTokenOnAllPosts,而您的名称为ValidateAntiForgeryTokenAttribute,因此调用不是递归的,因为该方法不会调用自身相同的论点。

您有三种选择 - 我不确定哪种情况最适合您的情况(我想的是第一种情况):

  • 将您的属性名称更改为ValidateAntiForgeryTokenOnAllPosts以匹配the example you posted中的名称。

  • 通过将块更改为

    来明确声明您想要System.Web.Mvc.ValidateAntiForgeryTokenAttribute
    new System.Web.Mvc.ValidateAntiForgeryTokenAttribute()
        .OnAuthorization(filterContext);
    
  • 由于您要覆盖ValidateAntiForgeryTokenAttribute,您可以调用基本方法,即

    else
    {
        base.OnAuthorization(filterContext);
    }