AntiForgery.Validate()vs ValidateAntiForgeryToken

时间:2014-03-18 12:47:07

标签: asp.net-mvc-4 antiforgerytoken

方法System.Web.Helpers.AntiForgery.Validate(); 执行与[ValidateAntiForgeryToken]装饰完全相同的功能?

我正在考虑更改我的注销方法:

    [HttpPost]        
    public virtual ActionResult LogOff()        
    {
        if (User.Identity.Name != "")
        {
            System.Web.Helpers.AntiForgery.Validate();
            WebSecurity.Logout();
        }           

        return RedirectToAction(MVC.Account.Login());
    }

这可以防止在系统因登录过期而退出时引发Anti Forgery异常。我只想确定AntiForgery.Validate()将执行与ValidateAntiForgeryToken相同的任务。

我正在使用额外的异常处理程序来捕获此异常。然而问题仍然是Elmah仍然记录了这个异常,而且我收到了许多消息。

1 个答案:

答案 0 :(得分:14)

似乎两种方法都会验证表单中存在的AntiForgeryToken。我检查了程序集,ValidateAntiForgeryTokenAttribute确实调用了AntiForgery.Validate方法来进行验证。当验证失败时,这两种方法都会抛出HttpValidateAntiForgeryException。因此,他们是否执行相同任务的简短答案是肯定的。

在OnAuthorization方法中,ValidateAntiForgeryTokenAttribute在MVC执行周期的早期验证令牌存在细微差别。如果在执行AntiForgeryToken.Validate()检查之前在控制器操作中执行资源密集型任务,这可能会对性能产生影响。

另外需要注意的是,您可能要为自己创建额外的工作(更不用说省略时可能存在的安全漏洞),要求每个HttpPost操作都有以下代码

if (User.Identity.Name != "")
{
    System.Web.Helpers.AntiForgery.Validate();
    WebSecurity.Logout();
}

通过创建以下属性并使用它来装饰这些帖子方法,您将拥有所需的功能,而不需要在每个帖子操作中都包含上述代码

using System;
using System.Web.Mvc;

[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class , AllowMultiple = false , Inherited = true )]
public class ValidateOrSignOutAntiForgeryTokenAttribute : 
    FilterAttribute , 
    IAuthorizationFilter
{

    public void OnAuthorization( AuthorizationContext filterContext )
    {
        if( filterContext == null )
        {
            throw new ArgumentNullException( "filterContext" );
        }

        if( filterContext.HttpContext.User != null &&
            filterContext.HttpContext.User.Identity.Name != "" )
        {
            try
            {
                System.Web.Helpers.AntiForgery.Validate();
            }
            catch
            {
                WebSecurity.Logout();
                throw;
            }
        }
    }

}

最后一点,AntiForgery验证中的例外是正常的。这是因为AntiForgery.Validate方法在验证失败时抛出HttpValidateAntiForgeryException。正如您在上面的代码中看到的,我已经捕获了此异常并在完成注销后重新抛出它。